@duckcodeailabs/dql-agent 1.13.5 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-run-engine.d.ts +79 -4
- package/dist/agent-run-engine.d.ts.map +1 -1
- package/dist/agent-run-engine.js +457 -39
- package/dist/agent-run-engine.js.map +1 -1
- package/dist/agent-run-gates.d.ts.map +1 -1
- package/dist/agent-run-gates.js +13 -0
- package/dist/agent-run-gates.js.map +1 -1
- package/dist/agent-run-store.d.ts.map +1 -1
- package/dist/agent-run-store.js +42 -25
- package/dist/agent-run-store.js.map +1 -1
- package/dist/agentic/analyst-loop.d.ts +91 -0
- package/dist/agentic/analyst-loop.d.ts.map +1 -0
- package/dist/agentic/analyst-loop.js +311 -0
- package/dist/agentic/analyst-loop.js.map +1 -0
- package/dist/agentic/assumptions.d.ts +62 -0
- package/dist/agentic/assumptions.d.ts.map +1 -0
- package/dist/agentic/assumptions.js +73 -0
- package/dist/agentic/assumptions.js.map +1 -0
- package/dist/agentic/business-explanation.d.ts +56 -0
- package/dist/agentic/business-explanation.d.ts.map +1 -0
- package/dist/agentic/business-explanation.js +130 -0
- package/dist/agentic/business-explanation.js.map +1 -0
- package/dist/agentic/identifier-ledger.d.ts +74 -0
- package/dist/agentic/identifier-ledger.d.ts.map +1 -0
- package/dist/agentic/identifier-ledger.js +151 -0
- package/dist/agentic/identifier-ledger.js.map +1 -0
- package/dist/agentic/ledger-tools.d.ts +68 -0
- package/dist/agentic/ledger-tools.d.ts.map +1 -0
- package/dist/agentic/ledger-tools.js +198 -0
- package/dist/agentic/ledger-tools.js.map +1 -0
- package/dist/agentic/orchestrator-policy.d.ts +60 -0
- package/dist/agentic/orchestrator-policy.d.ts.map +1 -0
- package/dist/agentic/orchestrator-policy.js +73 -0
- package/dist/agentic/orchestrator-policy.js.map +1 -0
- package/dist/agentic/orchestrator.d.ts +54 -0
- package/dist/agentic/orchestrator.d.ts.map +1 -0
- package/dist/agentic/orchestrator.js +67 -0
- package/dist/agentic/orchestrator.js.map +1 -0
- package/dist/agentic/preview-tool.d.ts +36 -0
- package/dist/agentic/preview-tool.d.ts.map +1 -0
- package/dist/agentic/preview-tool.js +71 -0
- package/dist/agentic/preview-tool.js.map +1 -0
- package/dist/agentic/rerank.d.ts +50 -0
- package/dist/agentic/rerank.d.ts.map +1 -0
- package/dist/agentic/rerank.js +140 -0
- package/dist/agentic/rerank.js.map +1 -0
- package/dist/agentic/research/hypothesis.d.ts +110 -0
- package/dist/agentic/research/hypothesis.d.ts.map +1 -0
- package/dist/agentic/research/hypothesis.js +125 -0
- package/dist/agentic/research/hypothesis.js.map +1 -0
- package/dist/agentic/research/synthesis.d.ts +32 -0
- package/dist/agentic/research/synthesis.d.ts.map +1 -0
- package/dist/agentic/research/synthesis.js +94 -0
- package/dist/agentic/research/synthesis.js.map +1 -0
- package/dist/agentic/research-agent.d.ts +54 -0
- package/dist/agentic/research-agent.d.ts.map +1 -0
- package/dist/agentic/research-agent.js +176 -0
- package/dist/agentic/research-agent.js.map +1 -0
- package/dist/agentic/sql-authorization.d.ts +131 -0
- package/dist/agentic/sql-authorization.d.ts.map +1 -0
- package/dist/agentic/sql-authorization.js +232 -0
- package/dist/agentic/sql-authorization.js.map +1 -0
- package/dist/agentic/tool-loop.d.ts +29 -0
- package/dist/agentic/tool-loop.d.ts.map +1 -1
- package/dist/agentic/tool-loop.js +129 -52
- package/dist/agentic/tool-loop.js.map +1 -1
- package/dist/agentic/toolset.d.ts.map +1 -1
- package/dist/agentic/toolset.js +155 -0
- package/dist/agentic/toolset.js.map +1 -1
- package/dist/agentic/turn-plan.d.ts +35 -0
- package/dist/agentic/turn-plan.d.ts.map +1 -0
- package/dist/agentic/turn-plan.js +108 -0
- package/dist/agentic/turn-plan.js.map +1 -0
- package/dist/agentic/value-probe.d.ts +89 -0
- package/dist/agentic/value-probe.d.ts.map +1 -0
- package/dist/agentic/value-probe.js +304 -0
- package/dist/agentic/value-probe.js.map +1 -0
- package/dist/analytical-orchestration.d.ts +336 -0
- package/dist/analytical-orchestration.d.ts.map +1 -0
- package/dist/analytical-orchestration.js +631 -0
- package/dist/analytical-orchestration.js.map +1 -0
- package/dist/analytical-request-policy.d.ts +26 -0
- package/dist/analytical-request-policy.d.ts.map +1 -0
- package/dist/analytical-request-policy.js +82 -0
- package/dist/analytical-request-policy.js.map +1 -0
- package/dist/analytical-result-facts.d.ts +14 -1
- package/dist/analytical-result-facts.d.ts.map +1 -1
- package/dist/analytical-result-facts.js +76 -1
- package/dist/analytical-result-facts.js.map +1 -1
- package/dist/answer-loop.d.ts +61 -16
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +256 -36
- package/dist/answer-loop.js.map +1 -1
- package/dist/cascade/budgets.d.ts.map +1 -1
- package/dist/cascade/budgets.js +8 -1
- package/dist/cascade/budgets.js.map +1 -1
- package/dist/cascade/packer.d.ts +88 -0
- package/dist/cascade/packer.d.ts.map +1 -0
- package/dist/cascade/packer.js +106 -0
- package/dist/cascade/packer.js.map +1 -0
- package/dist/conversation/result-ops.d.ts +18 -3
- package/dist/conversation/result-ops.d.ts.map +1 -1
- package/dist/conversation/result-ops.js +77 -5
- package/dist/conversation/result-ops.js.map +1 -1
- package/dist/conversation/rolling-summary.d.ts.map +1 -1
- package/dist/conversation/rolling-summary.js +7 -2
- package/dist/conversation/rolling-summary.js.map +1 -1
- package/dist/conversation/session-store.d.ts +3 -0
- package/dist/conversation/session-store.d.ts.map +1 -1
- package/dist/conversation/session-store.js +8 -4
- package/dist/conversation/session-store.js.map +1 -1
- package/dist/conversation/snapshot.d.ts.map +1 -1
- package/dist/conversation/snapshot.js +13 -1
- package/dist/conversation/snapshot.js.map +1 -1
- package/dist/conversation/turn-trust.d.ts.map +1 -1
- package/dist/conversation/turn-trust.js +6 -0
- package/dist/conversation/turn-trust.js.map +1 -1
- package/dist/hints/store.d.ts.map +1 -1
- package/dist/hints/store.js +15 -5
- package/dist/hints/store.js.map +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -4
- package/dist/index.js.map +1 -1
- package/dist/intent-controller.d.ts +8 -0
- package/dist/intent-controller.d.ts.map +1 -1
- package/dist/intent-controller.js +65 -0
- package/dist/intent-controller.js.map +1 -1
- package/dist/meaning-resolution.d.ts +7 -0
- package/dist/meaning-resolution.d.ts.map +1 -1
- package/dist/meaning-resolution.js.map +1 -1
- package/dist/metadata/block-fit.d.ts +18 -0
- package/dist/metadata/block-fit.d.ts.map +1 -1
- package/dist/metadata/block-fit.js +41 -1
- package/dist/metadata/block-fit.js.map +1 -1
- package/dist/metadata/catalog.d.ts +44 -23
- package/dist/metadata/catalog.d.ts.map +1 -1
- package/dist/metadata/catalog.js +363 -53
- package/dist/metadata/catalog.js.map +1 -1
- package/dist/metadata/meaning-evidence.d.ts.map +1 -1
- package/dist/metadata/meaning-evidence.js +101 -8
- package/dist/metadata/meaning-evidence.js.map +1 -1
- package/dist/metadata/metric-match.d.ts +32 -0
- package/dist/metadata/metric-match.d.ts.map +1 -1
- package/dist/metadata/metric-match.js +120 -9
- package/dist/metadata/metric-match.js.map +1 -1
- package/dist/research-loop.d.ts +33 -2
- package/dist/research-loop.d.ts.map +1 -1
- package/dist/research-loop.js +44 -4
- package/dist/research-loop.js.map +1 -1
- package/dist/resolved-analytical-plan.d.ts.map +1 -1
- package/dist/resolved-analytical-plan.js +92 -5
- package/dist/resolved-analytical-plan.js.map +1 -1
- package/dist/router.d.ts +36 -16
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +604 -25
- package/dist/router.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/** Values that must never be probed, whatever the configuration says. */
|
|
2
|
+
/**
|
|
3
|
+
* Hard deny. No configuration overrides this.
|
|
4
|
+
*
|
|
5
|
+
* Three groups, and the reason each is here:
|
|
6
|
+
* SECRETS — a probe returns literal values, so one match leaks the secret.
|
|
7
|
+
* FREE TEXT — a note or description can contain anything, including all of
|
|
8
|
+
* the above, so its shape gives no safety.
|
|
9
|
+
* DIRECT AND REGULATED IDENTIFIERS — payment, government, contact, health,
|
|
10
|
+
* and compensation fields. A probe over these is a data-protection
|
|
11
|
+
* incident even when the query is otherwise correct, and "the model asked
|
|
12
|
+
* for it" is not a defence. Added after a live run answered a request for
|
|
13
|
+
* credit-card numbers and home addresses from the nearest certified block.
|
|
14
|
+
*
|
|
15
|
+
* Deliberately broad. A false deny costs one value lookup; a false allow
|
|
16
|
+
* cannot be undone once the values have left the warehouse.
|
|
17
|
+
*/
|
|
18
|
+
const DENY_RE = /\b(password|passwd|secret|token|credential|apikey|api key|private key|hash|salt|signature|session|cookie|auth|otp|pin)\b|\b(notes?|comments?|description|message|body|payload|content|remarks?|feedback|reason)\b|\b(ssn|social security|social insurance|sin\b|dob|date of birth|birth date|birthdate|national id|government id|government identifier|tax id|taxpayer id|taxpayer identification|tin\b|itin\b|ein\b|medicare|medicaid|passport|license|licence|driver license|visa|nric|aadhaar)\b|\b(card|cardnumber|card number|credit card|debit card|cvv|cvc|iban|swift|bic|routing|account number|acct|sort code|bank)\b|\b(address|street|postal|postcode|zip|zipcode|latitude|longitude|geo|coordinates?)\b|\b(phone|mobile|telephone|fax|contact number)\b|\b(salary|compensation|wage|payroll|bonus|income|net pay|gross pay)\b|\b(medical|diagnosis|patient|health|insurance|prescription|disability|biometric|fingerprint|race|ethnicity|religion|gender|sexual)\b/;
|
|
19
|
+
/** Email is denied separately: it is an identifier, but also direct PII. */
|
|
20
|
+
const EMAIL_RE = /\bemail\b/;
|
|
21
|
+
/** Name shapes that plausibly identify an entity rather than describe one. */
|
|
22
|
+
const IDENTIFIER_TOKENS = new Set([
|
|
23
|
+
'account', 'category', 'channel', 'city', 'code', 'country', 'customer',
|
|
24
|
+
'full', 'id', 'key', 'member', 'name', 'number', 'product', 'region',
|
|
25
|
+
'segment', 'sku', 'state', 'status', 'subscriber', 'tier', 'type', 'user',
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* Token-level aliases that must remain denied even when a connector exposes
|
|
29
|
+
* them with underscores, dashes, or camel case rather than the prose phrases
|
|
30
|
+
* above. The phrase regex is intentionally broad, but `tax_number` and
|
|
31
|
+
* `customerBirthDt` never contain the literal phrase "tax id" or "birth
|
|
32
|
+
* date". Normalise the identifier into tokens before the allow-list gets a
|
|
33
|
+
* chance to treat its `number` / `customer` part as a business key.
|
|
34
|
+
*/
|
|
35
|
+
const SENSITIVE_IDENTIFIER_PREFIXES = new Set([
|
|
36
|
+
'government', 'govt', 'national', 'tax', 'taxpayer',
|
|
37
|
+
]);
|
|
38
|
+
const SENSITIVE_IDENTIFIER_SUFFIXES = new Set([
|
|
39
|
+
'id', 'identifier', 'number', 'no', 'num',
|
|
40
|
+
]);
|
|
41
|
+
// Connector metadata often elides separators inside an otherwise ordinary
|
|
42
|
+
// entity identifier (for example `customer_taxnumber`). Match only a
|
|
43
|
+
// sensitive alias at the end of the compact identifier: this catches the
|
|
44
|
+
// sensitive suffix without turning `customer_id` or `product_number` into a
|
|
45
|
+
// false positive.
|
|
46
|
+
const COMPACT_SENSITIVE_IDENTIFIER_ALIAS_RE = /(?:taxpayer|tax|government|govt|national)(?:id|identifier|number|no|num)$/;
|
|
47
|
+
const COMPACT_BIRTH_DATE_ALIAS_RE = /(?:birth(?:date|dt|day|dob|on)|dateofbirth|birthday)$/;
|
|
48
|
+
/** Types that can hold a searchable literal. */
|
|
49
|
+
const TEXTUAL_TYPE_RE = /\b(char|character|clob|string|text|uuid|varchar|nvarchar)\b/;
|
|
50
|
+
function tokenize(name) {
|
|
51
|
+
return new Set(name
|
|
52
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
53
|
+
.replace(/[_\-.]+/g, ' ')
|
|
54
|
+
.toLowerCase()
|
|
55
|
+
.split(/\s+/)
|
|
56
|
+
.filter(Boolean));
|
|
57
|
+
}
|
|
58
|
+
function isSensitiveIdentifierAlias(tokens) {
|
|
59
|
+
const has = (...values) => values.some((value) => tokens.has(value));
|
|
60
|
+
const compact = [...tokens].join('');
|
|
61
|
+
if (COMPACT_SENSITIVE_IDENTIFIER_ALIAS_RE.test(compact) || COMPACT_BIRTH_DATE_ALIAS_RE.test(compact)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
// `date_of_birth`, `customer_birth_dt`, and `customerDOB` are all direct
|
|
65
|
+
// personal identifiers despite their otherwise identifier-shaped names.
|
|
66
|
+
if (has('dob') || (has('birth') && has('date', 'dt', 'day', 'on')))
|
|
67
|
+
return true;
|
|
68
|
+
// Treat a government/tax qualifier plus an identifier suffix as sensitive.
|
|
69
|
+
// This intentionally does not deny ordinary business identifiers such as
|
|
70
|
+
// `customer_id`, `product_number`, or `order_code`.
|
|
71
|
+
return has(...SENSITIVE_IDENTIFIER_PREFIXES)
|
|
72
|
+
&& has(...SENSITIVE_IDENTIFIER_SUFFIXES);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* May this column be probed for a literal?
|
|
76
|
+
*
|
|
77
|
+
* Canonical implementation — the host's `isAgentValueProbeColumn` delegates here
|
|
78
|
+
* so the deny-list has exactly one definition. Two copies of a security rule
|
|
79
|
+
* drift, and the one that drifts is the one nobody is looking at.
|
|
80
|
+
*/
|
|
81
|
+
export function isProbeSafeColumn(column) {
|
|
82
|
+
const normalized = column.name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_\-.]+/g, ' ').toLowerCase();
|
|
83
|
+
if (DENY_RE.test(normalized))
|
|
84
|
+
return false;
|
|
85
|
+
if (EMAIL_RE.test(normalized))
|
|
86
|
+
return false;
|
|
87
|
+
const tokens = tokenize(column.name);
|
|
88
|
+
if (isSensitiveIdentifierAlias(tokens))
|
|
89
|
+
return false;
|
|
90
|
+
if (![...tokens].some((token) => IDENTIFIER_TOKENS.has(token)))
|
|
91
|
+
return false;
|
|
92
|
+
const type = column.type?.toLowerCase() ?? '';
|
|
93
|
+
// An unknown type is allowed: many drivers omit it, and the name gates already
|
|
94
|
+
// passed. A KNOWN non-textual type is not — a literal cannot live in a float.
|
|
95
|
+
if (!type)
|
|
96
|
+
return true;
|
|
97
|
+
return TEXTUAL_TYPE_RE.test(type);
|
|
98
|
+
}
|
|
99
|
+
/** Escape a single-quoted SQL literal. */
|
|
100
|
+
function sqlLiteral(value) {
|
|
101
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
102
|
+
}
|
|
103
|
+
/** Quote an identifier ANSI-style, rejecting anything that is not a plain name. */
|
|
104
|
+
function quoteIdentifier(value) {
|
|
105
|
+
// Identifiers come from the SCHEMA, never from the user, so anything exotic
|
|
106
|
+
// here means a caller is passing something it should not.
|
|
107
|
+
if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(value))
|
|
108
|
+
return undefined;
|
|
109
|
+
return `"${value}"`;
|
|
110
|
+
}
|
|
111
|
+
function quoteRelation(relation) {
|
|
112
|
+
const parts = relation.split('.').map(quoteIdentifier);
|
|
113
|
+
return parts.every(Boolean) ? parts.join('.') : undefined;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Build a bounded DISTINCT lookup for one column.
|
|
117
|
+
*
|
|
118
|
+
* Exact match first, then a prefix match on the longer tokens. Prefix rather
|
|
119
|
+
* than `%term%`: a leading wildcard cannot use an index, and on a large
|
|
120
|
+
* dimension table that is the difference between a probe and an outage.
|
|
121
|
+
*/
|
|
122
|
+
export function buildValueProbeSql(relation, column, terms, limit = 25) {
|
|
123
|
+
const quotedRelation = quoteRelation(relation);
|
|
124
|
+
const quotedColumn = quoteIdentifier(column);
|
|
125
|
+
if (!quotedRelation || !quotedColumn)
|
|
126
|
+
return undefined;
|
|
127
|
+
const cast = `LOWER(CAST(${quotedColumn} AS VARCHAR))`;
|
|
128
|
+
const predicates = [];
|
|
129
|
+
for (const term of terms) {
|
|
130
|
+
const normalized = term.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
131
|
+
if (!normalized)
|
|
132
|
+
continue;
|
|
133
|
+
predicates.push(`${cast} = ${sqlLiteral(normalized)}`);
|
|
134
|
+
for (const token of normalized.split(' ').filter((part) => part.length >= 4).slice(0, 2)) {
|
|
135
|
+
predicates.push(`${cast} LIKE ${sqlLiteral(`${token.replace(/[%_\\]/g, '\\$&')}%`)} ESCAPE '\\'`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (predicates.length === 0)
|
|
139
|
+
return undefined;
|
|
140
|
+
return [
|
|
141
|
+
`SELECT DISTINCT CAST(${quotedColumn} AS VARCHAR) AS value`,
|
|
142
|
+
`FROM ${quotedRelation}`,
|
|
143
|
+
`WHERE ${quotedColumn} IS NOT NULL AND (${[...new Set(predicates)].slice(0, 8).join(' OR ')})`,
|
|
144
|
+
`LIMIT ${Math.max(1, Math.min(limit, 50))}`,
|
|
145
|
+
].join('\n');
|
|
146
|
+
}
|
|
147
|
+
/** The total maximum value-probe queries a single tool call may issue. */
|
|
148
|
+
export const MAX_VALUE_PROBE_COLUMN_QUERIES = 12;
|
|
149
|
+
/**
|
|
150
|
+
* A tool that answers "does this literal exist, and in which column?".
|
|
151
|
+
*
|
|
152
|
+
* Returns the matched VALUES — which is the point, since the loop needs the
|
|
153
|
+
* exact stored spelling to build a filter — but only from columns that passed
|
|
154
|
+
* both gates, and only values the caller already named.
|
|
155
|
+
*/
|
|
156
|
+
export function buildSearchValuesTool(options) {
|
|
157
|
+
const maxRelations = options.maxRelations ?? 6;
|
|
158
|
+
const maxColumnQueries = Math.max(1, Math.min(options.maxColumnQueries ?? MAX_VALUE_PROBE_COLUMN_QUERIES, MAX_VALUE_PROBE_COLUMN_QUERIES));
|
|
159
|
+
return {
|
|
160
|
+
name: 'search_values',
|
|
161
|
+
description: 'Check whether a literal the question names (a customer, product, region, status) exists as a value in the data, and get its exact stored spelling. Use it BEFORE filtering on a name, so a filter is built from a real value rather than a guess. Only searches columns approved for value lookup.',
|
|
162
|
+
inputSchema: {
|
|
163
|
+
type: 'object',
|
|
164
|
+
additionalProperties: false,
|
|
165
|
+
required: ['terms'],
|
|
166
|
+
properties: {
|
|
167
|
+
terms: { type: 'array', items: { type: 'string' }, description: 'Literals named in the question, e.g. ["Wesley Jenkins"].' },
|
|
168
|
+
relations: { type: 'array', items: { type: 'string' }, description: 'Optional relations to restrict the search to.' },
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
run: async (args) => {
|
|
172
|
+
const input = (args && typeof args === 'object' ? args : {});
|
|
173
|
+
const terms = Array.isArray(input.terms)
|
|
174
|
+
? input.terms.filter((term) => typeof term === 'string' && term.trim().length > 0)
|
|
175
|
+
: [];
|
|
176
|
+
if (terms.length === 0)
|
|
177
|
+
return { error: 'Pass the literal(s) to look up, e.g. ["Wesley Jenkins"].' };
|
|
178
|
+
if (!options.enabled) {
|
|
179
|
+
// Say WHY, and name the setting. A silent empty result here is what
|
|
180
|
+
// produced the false-absence defect: the loop concluded the value did
|
|
181
|
+
// not exist when it had simply never been allowed to look.
|
|
182
|
+
return {
|
|
183
|
+
searched: false,
|
|
184
|
+
reason: 'Value lookup is disabled for this project. Enable agent.runtimeValueGrounding in dql.config.json to let DQL confirm a named value before filtering on it.',
|
|
185
|
+
matches: [],
|
|
186
|
+
coverage: {
|
|
187
|
+
version: 1,
|
|
188
|
+
status: 'disabled',
|
|
189
|
+
queryLimit: maxColumnQueries,
|
|
190
|
+
queriesAttempted: 0,
|
|
191
|
+
relationsRequested: [],
|
|
192
|
+
relationsSearched: [],
|
|
193
|
+
relationsWithNoSearchableColumn: [],
|
|
194
|
+
relationsWithUnbuildableIdentifier: [],
|
|
195
|
+
failedRelations: [],
|
|
196
|
+
unknownRelations: [],
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
const requestedRelations = Array.isArray(input.relations)
|
|
201
|
+
? [...new Set(input.relations.filter((r) => typeof r === 'string' && r.trim().length > 0).map((r) => r.trim()))]
|
|
202
|
+
: [];
|
|
203
|
+
const wanted = requestedRelations.length > 0
|
|
204
|
+
? new Set(requestedRelations.map((relation) => relation.toLowerCase()))
|
|
205
|
+
: undefined;
|
|
206
|
+
const knownRelations = new Set(options.relations.map((relation) => relation.relation.toLowerCase()));
|
|
207
|
+
const unknownRelations = requestedRelations.filter((relation) => !knownRelations.has(relation.toLowerCase()));
|
|
208
|
+
const matches = [];
|
|
209
|
+
const searched = [];
|
|
210
|
+
const skipped = [];
|
|
211
|
+
const unbuildableRelations = new Set();
|
|
212
|
+
const failedRelations = new Set();
|
|
213
|
+
let queriesAttempted = 0;
|
|
214
|
+
let relationBudgetExceeded = false;
|
|
215
|
+
let queryBudgetExceeded = false;
|
|
216
|
+
let relationsConsidered = 0;
|
|
217
|
+
for (const relation of options.relations) {
|
|
218
|
+
if (wanted && !wanted.has(relation.relation.toLowerCase()))
|
|
219
|
+
continue;
|
|
220
|
+
if (relationsConsidered >= maxRelations) {
|
|
221
|
+
relationBudgetExceeded = true;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
relationsConsidered += 1;
|
|
225
|
+
const safe = relation.columns.filter(isProbeSafeColumn);
|
|
226
|
+
if (safe.length === 0) {
|
|
227
|
+
skipped.push(relation.relation);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
for (const column of safe) {
|
|
231
|
+
if (queriesAttempted >= maxColumnQueries) {
|
|
232
|
+
queryBudgetExceeded = true;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
const sql = buildValueProbeSql(relation.relation, column.name, terms);
|
|
236
|
+
if (!sql) {
|
|
237
|
+
// Metadata identifiers are not automatically executable SQL
|
|
238
|
+
// identifiers. Never turn an unquotable schema name into a
|
|
239
|
+
// zero-query "not found" claim.
|
|
240
|
+
unbuildableRelations.add(relation.relation);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (!searched.includes(relation.relation))
|
|
244
|
+
searched.push(relation.relation);
|
|
245
|
+
queriesAttempted += 1;
|
|
246
|
+
try {
|
|
247
|
+
const result = await options.execute(sql);
|
|
248
|
+
const values = (result.rows ?? [])
|
|
249
|
+
.map((row) => (Array.isArray(row) ? row[0] : row?.value))
|
|
250
|
+
.filter((value) => typeof value === 'string');
|
|
251
|
+
if (values.length > 0)
|
|
252
|
+
matches.push({ relation: relation.relation, column: column.name, values });
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// One unreadable relation must not fail the whole probe; a permission
|
|
256
|
+
// error on a single table is normal in a governed warehouse.
|
|
257
|
+
failedRelations.add(relation.relation);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (queryBudgetExceeded)
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
const complete = unknownRelations.length === 0
|
|
264
|
+
&& failedRelations.size === 0
|
|
265
|
+
&& skipped.length === 0
|
|
266
|
+
&& unbuildableRelations.size === 0
|
|
267
|
+
&& !relationBudgetExceeded
|
|
268
|
+
&& !queryBudgetExceeded;
|
|
269
|
+
const status = unknownRelations.length > 0
|
|
270
|
+
? 'unknown_relation'
|
|
271
|
+
: queryBudgetExceeded || relationBudgetExceeded
|
|
272
|
+
? 'budget_exhausted'
|
|
273
|
+
: complete
|
|
274
|
+
? 'complete'
|
|
275
|
+
: 'partial';
|
|
276
|
+
const coverage = {
|
|
277
|
+
version: 1,
|
|
278
|
+
status,
|
|
279
|
+
queryLimit: maxColumnQueries,
|
|
280
|
+
queriesAttempted,
|
|
281
|
+
relationsRequested: requestedRelations,
|
|
282
|
+
relationsSearched: searched,
|
|
283
|
+
relationsWithNoSearchableColumn: skipped,
|
|
284
|
+
relationsWithUnbuildableIdentifier: [...unbuildableRelations],
|
|
285
|
+
failedRelations: [...failedRelations],
|
|
286
|
+
unknownRelations,
|
|
287
|
+
};
|
|
288
|
+
return {
|
|
289
|
+
searched: searched.length > 0,
|
|
290
|
+
terms,
|
|
291
|
+
matches,
|
|
292
|
+
relationsSearched: searched,
|
|
293
|
+
...(skipped.length > 0 ? { relationsWithNoSearchableColumn: skipped } : {}),
|
|
294
|
+
coverage,
|
|
295
|
+
// Absence is a claim, not a default for an empty array. Only an
|
|
296
|
+
// exhaustive, error-free scan of the approved scope may support it.
|
|
297
|
+
...(matches.length === 0 && complete
|
|
298
|
+
? { absence: 'not_found', note: 'Searched the approved columns and found no match for these literals.' }
|
|
299
|
+
: {}),
|
|
300
|
+
};
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=value-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-probe.js","sourceRoot":"","sources":["../../src/agentic/value-probe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared contracts for the conversational analytical orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* The existing DQL engine remains the authority for compilation, execution,
|
|
5
|
+
* trust, and the immutable resolved analytical plan. This module is the thin
|
|
6
|
+
* outer contract used by the conversational layer to describe what it
|
|
7
|
+
* understood, what it searched, and why it could or could not continue.
|
|
8
|
+
*
|
|
9
|
+
* The contract is intentionally content-only: it never carries model
|
|
10
|
+
* chain-of-thought, credentials, raw provider payloads, or authorization.
|
|
11
|
+
*
|
|
12
|
+
* Acceptance: AGT-027..033, CTX-007, PERF-003, E2E-022.
|
|
13
|
+
*/
|
|
14
|
+
import type { DqlArtifactExecutionReceipt } from '@duckcodeailabs/dql-core';
|
|
15
|
+
export declare const ANALYTICAL_ORCHESTRATION_CONTRACT_VERSION: 1;
|
|
16
|
+
export type AnalyticalTurnKind = 'conversation' | 'definition' | 'lookup' | 'ranking' | 'breakdown' | 'comparison' | 'drilldown' | 'diagnosis' | 'research' | 'compound' | 'clarification' | 'aggregation';
|
|
17
|
+
export type AnalyticalTaskKind = 'definition' | 'aggregation' | 'ranking' | 'attribute_lookup' | 'breakdown' | 'comparison' | 'drilldown' | 'diagnosis' | 'research_branch';
|
|
18
|
+
export type AnalyticalTaskStatus = 'planned' | 'running' | 'completed' | 'partial' | 'gap' | 'blocked';
|
|
19
|
+
export interface AnalyticalTaskOutputContractV1 {
|
|
20
|
+
metrics: string[];
|
|
21
|
+
dimensions: string[];
|
|
22
|
+
filters: Array<{
|
|
23
|
+
field: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}>;
|
|
26
|
+
grain?: string;
|
|
27
|
+
limit?: number;
|
|
28
|
+
order?: 'asc' | 'desc';
|
|
29
|
+
requestedColumns?: string[];
|
|
30
|
+
}
|
|
31
|
+
/** A bounded, server-computed dependency between two compound tasks. */
|
|
32
|
+
export interface AnalyticalTaskDependencyV1 {
|
|
33
|
+
version: 1;
|
|
34
|
+
kind: 'top_ranked_region';
|
|
35
|
+
sourceTaskId: string;
|
|
36
|
+
targetDimension: 'region';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The only parent-result material a dependent child may receive. It carries
|
|
40
|
+
* one selected canonical value and its row/result proofs, never parent prose,
|
|
41
|
+
* SQL, or arbitrary rows.
|
|
42
|
+
*/
|
|
43
|
+
export interface AnalyticalTaskDependencyBindingV1 {
|
|
44
|
+
version: 1;
|
|
45
|
+
sourceTaskId: string;
|
|
46
|
+
sourceResultFingerprint: string;
|
|
47
|
+
canonicalColumn: string;
|
|
48
|
+
value: string;
|
|
49
|
+
rowFingerprint: string;
|
|
50
|
+
}
|
|
51
|
+
export type AnalyticalTaskDependencyResolution = {
|
|
52
|
+
ok: true;
|
|
53
|
+
binding: AnalyticalTaskDependencyBindingV1;
|
|
54
|
+
} | {
|
|
55
|
+
ok: false;
|
|
56
|
+
code: 'RESULT_CONTRACT_MISMATCH';
|
|
57
|
+
message: string;
|
|
58
|
+
};
|
|
59
|
+
export interface AnalyticalTaskV1 {
|
|
60
|
+
version: 1;
|
|
61
|
+
id: string;
|
|
62
|
+
kind: AnalyticalTaskKind;
|
|
63
|
+
question: string;
|
|
64
|
+
dependencies: string[];
|
|
65
|
+
dependency?: AnalyticalTaskDependencyV1;
|
|
66
|
+
output: AnalyticalTaskOutputContractV1;
|
|
67
|
+
status: AnalyticalTaskStatus;
|
|
68
|
+
/** Only qualified catalog IDs may be placed in this list. */
|
|
69
|
+
candidateIds: string[];
|
|
70
|
+
/** Shared prior-result bindings, e.g. region = Philadelphia. */
|
|
71
|
+
inheritedBindings: Array<{
|
|
72
|
+
id: string;
|
|
73
|
+
value: string;
|
|
74
|
+
source: 'conversation' | 'result' | 'user';
|
|
75
|
+
}>;
|
|
76
|
+
}
|
|
77
|
+
/** Durable, content-only outcome for one independent clause/branch. */
|
|
78
|
+
export interface AnalyticalTaskOutcomeV1 {
|
|
79
|
+
version: 1;
|
|
80
|
+
taskId: string;
|
|
81
|
+
status: 'completed' | 'partial' | 'gap' | 'blocked';
|
|
82
|
+
summary?: string;
|
|
83
|
+
resultFingerprint?: string;
|
|
84
|
+
gap?: AnalyticalCoverageGapV1;
|
|
85
|
+
}
|
|
86
|
+
export interface AnalyticalCoverageGapV1 {
|
|
87
|
+
version: 1;
|
|
88
|
+
code: 'MISSING_MEASURE' | 'MISSING_DIMENSION' | 'MISSING_ATTRIBUTE' | 'MISSING_RELATIONSHIP' | 'MISSING_RUNTIME_CAPABILITY' | 'RESULT_CONTRACT_MISMATCH' | 'PROVIDER_UNAVAILABLE' | 'EXECUTION_FAILED' | 'AMBIGUOUS_MEANING' | 'POLICY_BLOCKED';
|
|
89
|
+
phase: 'retrieval' | 'meaning' | 'planning' | 'compilation' | 'execution' | 'presentation';
|
|
90
|
+
message: string;
|
|
91
|
+
searchedSources: string[];
|
|
92
|
+
attemptedRoutes: Array<'certified' | 'semantic' | 'governed_relational' | 'generated' | 'research'>;
|
|
93
|
+
missing: string[];
|
|
94
|
+
recoverable: boolean;
|
|
95
|
+
planFrozen: boolean;
|
|
96
|
+
nextActions: string[];
|
|
97
|
+
}
|
|
98
|
+
export interface AnalyticalTurnPlanV1 {
|
|
99
|
+
version: 1;
|
|
100
|
+
turnId?: string;
|
|
101
|
+
question: string;
|
|
102
|
+
kind: AnalyticalTurnKind;
|
|
103
|
+
/** Natural-language turns use one bounded interpretation call by default. */
|
|
104
|
+
meaningCallBudget: 0 | 1;
|
|
105
|
+
meaningCallReason: 'explicit_binding' | 'conversation_only' | 'candidate_interpretation' | 'frozen_research_child';
|
|
106
|
+
snapshotId?: string;
|
|
107
|
+
sourceFingerprint?: string;
|
|
108
|
+
taskIds: string[];
|
|
109
|
+
tasks: AnalyticalTaskV1[];
|
|
110
|
+
authorityOrder: Array<'certified' | 'semantic' | 'governed_relational' | 'generated'>;
|
|
111
|
+
/** This is set only after compatibility and authorization have passed. */
|
|
112
|
+
frozen: boolean;
|
|
113
|
+
conversationTurnId?: string;
|
|
114
|
+
parentRunId?: string;
|
|
115
|
+
}
|
|
116
|
+
export interface AnalyticalAnswerSectionV1 {
|
|
117
|
+
version: 1;
|
|
118
|
+
id: string;
|
|
119
|
+
taskId: string;
|
|
120
|
+
status: 'answered' | 'partial' | 'gap' | 'blocked';
|
|
121
|
+
answer?: string;
|
|
122
|
+
result?: CanonicalQueryResultV1;
|
|
123
|
+
gap?: AnalyticalCoverageGapV1;
|
|
124
|
+
factIds: string[];
|
|
125
|
+
trustState: 'certified' | 'governed' | 'review_required' | 'not_applicable' | 'blocked';
|
|
126
|
+
}
|
|
127
|
+
export interface AnalyticalTurnAnswerV1 {
|
|
128
|
+
version: 1;
|
|
129
|
+
answer: string;
|
|
130
|
+
sections: AnalyticalAnswerSectionV1[];
|
|
131
|
+
followUps: string[];
|
|
132
|
+
facts: string[];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Small, explainable intent vocabulary used before the physical plan exists.
|
|
136
|
+
* It is deliberately not a second semantic matcher: candidate identity still
|
|
137
|
+
* comes from retrieval plus the bounded meaning call. These helpers only turn
|
|
138
|
+
* a request into a task graph and output contract, so a compound question can
|
|
139
|
+
* report partial success instead of collapsing the whole turn to one error.
|
|
140
|
+
*/
|
|
141
|
+
export declare function inferAnalyticalTurnKind(question: string): AnalyticalTurnKind;
|
|
142
|
+
export declare function splitAnalyticalTasks(question: string): string[];
|
|
143
|
+
export declare function buildAnalyticalTaskGraph(input: {
|
|
144
|
+
question: string;
|
|
145
|
+
/**
|
|
146
|
+
* Explicit user-selected mode. Research is a root workflow, not merely a
|
|
147
|
+
* higher reasoning effort: its evidence ledger and synthesis must retain the
|
|
148
|
+
* whole question rather than treating story clauses as independent asks.
|
|
149
|
+
*/
|
|
150
|
+
mode?: 'ask' | 'research';
|
|
151
|
+
candidateIds?: string[];
|
|
152
|
+
metrics?: string[];
|
|
153
|
+
dimensions?: string[];
|
|
154
|
+
filters?: Array<{
|
|
155
|
+
field: string;
|
|
156
|
+
value: string;
|
|
157
|
+
}>;
|
|
158
|
+
inheritedBindings?: Array<{
|
|
159
|
+
id: string;
|
|
160
|
+
value: string;
|
|
161
|
+
source: 'conversation' | 'result' | 'user';
|
|
162
|
+
}>;
|
|
163
|
+
maxTasks?: number;
|
|
164
|
+
}): {
|
|
165
|
+
kind: AnalyticalTurnKind;
|
|
166
|
+
tasks: AnalyticalTaskV1[];
|
|
167
|
+
partial: boolean;
|
|
168
|
+
};
|
|
169
|
+
export declare function buildAnalyticalTurnPlan(input: {
|
|
170
|
+
question: string;
|
|
171
|
+
mode?: 'ask' | 'research';
|
|
172
|
+
turnId?: string;
|
|
173
|
+
candidateIds?: string[];
|
|
174
|
+
metrics?: string[];
|
|
175
|
+
dimensions?: string[];
|
|
176
|
+
filters?: Array<{
|
|
177
|
+
field: string;
|
|
178
|
+
value: string;
|
|
179
|
+
}>;
|
|
180
|
+
inheritedBindings?: Array<{
|
|
181
|
+
id: string;
|
|
182
|
+
value: string;
|
|
183
|
+
source: 'conversation' | 'result' | 'user';
|
|
184
|
+
}>;
|
|
185
|
+
zeroCallReason?: AnalyticalTurnPlanV1['meaningCallReason'];
|
|
186
|
+
frozen?: boolean;
|
|
187
|
+
snapshotId?: string;
|
|
188
|
+
sourceFingerprint?: string;
|
|
189
|
+
}): AnalyticalTurnPlanV1;
|
|
190
|
+
export declare function summarizeTaskOutcomes(tasks: AnalyticalTaskV1[]): {
|
|
191
|
+
status: 'completed' | 'partial' | 'gap' | 'blocked';
|
|
192
|
+
completed: string[];
|
|
193
|
+
gaps: string[];
|
|
194
|
+
};
|
|
195
|
+
export interface CanonicalQueryResultV1 {
|
|
196
|
+
version: 1;
|
|
197
|
+
columns: string[];
|
|
198
|
+
rows: Array<Record<string, unknown>>;
|
|
199
|
+
rowCount: number;
|
|
200
|
+
executionTime?: number;
|
|
201
|
+
truncated?: boolean;
|
|
202
|
+
/** The exact execution proof is carried through every transport boundary. */
|
|
203
|
+
executionReceipt?: DqlArtifactExecutionReceipt;
|
|
204
|
+
/** Trust/tier are descriptive identity, never inferred by a renderer. */
|
|
205
|
+
trustState?: 'certified' | 'governed' | 'review_required' | 'not_applicable' | 'blocked';
|
|
206
|
+
answerTier?: string;
|
|
207
|
+
resultFingerprint: string;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* A reader-selected value from a previously rendered canonical result.
|
|
211
|
+
*
|
|
212
|
+
* This is intentionally a reference, not copied conversational prose. The
|
|
213
|
+
* host must resolve `sourceRunId` from its durable run store and validate every
|
|
214
|
+
* field against the persisted result before the binding may influence routing,
|
|
215
|
+
* value lookup, or SQL planning.
|
|
216
|
+
*/
|
|
217
|
+
export interface AgentSelectedResultBindingV1 {
|
|
218
|
+
version: 1;
|
|
219
|
+
sourceRunId: string;
|
|
220
|
+
sourceArtifactId: string;
|
|
221
|
+
canonicalColumn: string;
|
|
222
|
+
value: string;
|
|
223
|
+
rowFingerprint: string;
|
|
224
|
+
resultFingerprint: string;
|
|
225
|
+
}
|
|
226
|
+
export type AgentSelectedResultBindingValidation = {
|
|
227
|
+
ok: true;
|
|
228
|
+
binding: AgentSelectedResultBindingV1;
|
|
229
|
+
} | {
|
|
230
|
+
ok: false;
|
|
231
|
+
code: 'RESULT_BINDING_INVALID' | 'RESULT_BINDING_RESULT_MISMATCH' | 'RESULT_BINDING_ROW_MISMATCH';
|
|
232
|
+
message: string;
|
|
233
|
+
};
|
|
234
|
+
/** Stable scalar transport for a selected canonical result cell. */
|
|
235
|
+
export declare function canonicalResultBindingValue(value: unknown): string | undefined;
|
|
236
|
+
/** A row proof includes all canonical columns, not just the selected cell. */
|
|
237
|
+
export declare function canonicalResultRowFingerprint(result: Pick<CanonicalQueryResultV1, 'columns'>, row: Record<string, unknown>): string;
|
|
238
|
+
/**
|
|
239
|
+
* Validate an untrusted selected-result reference against a persisted
|
|
240
|
+
* canonical result. The source run/artifact identities are checked by the
|
|
241
|
+
* host before calling this pure result-level validator.
|
|
242
|
+
*/
|
|
243
|
+
export declare function validateSelectedResultBinding(binding: AgentSelectedResultBindingV1 | undefined, result: CanonicalQueryResultV1 | undefined): AgentSelectedResultBindingValidation;
|
|
244
|
+
/**
|
|
245
|
+
* Derive the one value a `top region -> customers in that region` child may
|
|
246
|
+
* consume. A first row alone is never proof. The parent must either return an
|
|
247
|
+
* explicit rank, or be the server-computed descending ranking task and return
|
|
248
|
+
* at least two rows with one strictly-leading numeric measure. `rowCount` is
|
|
249
|
+
* the returned-row contract, not proof that a singleton is the complete group
|
|
250
|
+
* set. Ties and ambiguous result shapes remain a typed child gap.
|
|
251
|
+
*/
|
|
252
|
+
export declare function resolveTopRankedRegionDependency(sourceTaskId: string, result: CanonicalQueryResultV1 | undefined, parentTask?: Pick<AnalyticalTaskV1, 'kind' | 'output'>): AnalyticalTaskDependencyResolution;
|
|
253
|
+
/**
|
|
254
|
+
* Normalize connector, MetricFlow, and provider result shapes at one boundary.
|
|
255
|
+
* Connectors may return `ColumnMeta[]` and rows as arrays; UI surfaces should
|
|
256
|
+
* never need to guess how to index those rows.
|
|
257
|
+
*/
|
|
258
|
+
export declare function normalizeCanonicalQueryResult(input: {
|
|
259
|
+
columns?: unknown;
|
|
260
|
+
rows?: unknown;
|
|
261
|
+
rowCount?: unknown;
|
|
262
|
+
executionTime?: unknown;
|
|
263
|
+
executionTimeMs?: unknown;
|
|
264
|
+
truncated?: unknown;
|
|
265
|
+
resultFingerprint?: unknown;
|
|
266
|
+
executionReceipt?: unknown;
|
|
267
|
+
trustState?: unknown;
|
|
268
|
+
answerTier?: unknown;
|
|
269
|
+
}): CanonicalQueryResultV1;
|
|
270
|
+
export declare function canonicalResultRows(result: CanonicalQueryResultV1): unknown[][];
|
|
271
|
+
export declare function assertCanonicalResult(result: CanonicalQueryResultV1): void;
|
|
272
|
+
export interface ContextCandidateCardV1 {
|
|
273
|
+
id: string;
|
|
274
|
+
lane: 'exact' | 'lexical' | 'vector' | 'graph' | 'runtime_value' | 'domain' | 'skill' | 'conversation' | 'certified' | 'semantic' | 'relational' | 'business';
|
|
275
|
+
relevance: number;
|
|
276
|
+
trust?: 'certified' | 'semantic' | 'governed_sql' | 'exploratory';
|
|
277
|
+
compatible?: boolean;
|
|
278
|
+
summary?: string;
|
|
279
|
+
}
|
|
280
|
+
export interface ContextFusionDiagnosticsV1 {
|
|
281
|
+
lanes: Record<string, {
|
|
282
|
+
returned: number;
|
|
283
|
+
durationMs?: number;
|
|
284
|
+
status?: 'ok' | 'empty' | 'error' | 'skipped';
|
|
285
|
+
error?: string;
|
|
286
|
+
skippedReason?: string;
|
|
287
|
+
}>;
|
|
288
|
+
selectedIds: string[];
|
|
289
|
+
truncated: boolean;
|
|
290
|
+
}
|
|
291
|
+
export interface ContextFusionResultV1 {
|
|
292
|
+
candidates: ContextCandidateCardV1[];
|
|
293
|
+
diagnostics: ContextFusionDiagnosticsV1;
|
|
294
|
+
}
|
|
295
|
+
/** Reciprocal-rank fusion keeps recall across lexical, vector, and graph lanes. */
|
|
296
|
+
export declare function fuseContextCandidates(lanes: Record<string, ContextCandidateCardV1[]>, limit?: number): ContextFusionResultV1;
|
|
297
|
+
export declare function retrieveContextLanes(lanes: Record<string, () => Promise<ContextCandidateCardV1[]>>, limit?: number, maxConcurrent?: number): Promise<ContextFusionResultV1>;
|
|
298
|
+
export interface ResearchLedgerEntryV1 {
|
|
299
|
+
id: string;
|
|
300
|
+
branchId: string;
|
|
301
|
+
question: string;
|
|
302
|
+
status: 'observed' | 'failed' | 'skipped';
|
|
303
|
+
/** Optional complete execution proof; arbitrary IDs are never accepted. */
|
|
304
|
+
executionReceipt?: DqlArtifactExecutionReceipt;
|
|
305
|
+
resultFingerprint?: string;
|
|
306
|
+
rowCount?: number;
|
|
307
|
+
facts: string[];
|
|
308
|
+
receipts: string[];
|
|
309
|
+
error?: string;
|
|
310
|
+
}
|
|
311
|
+
export interface ResearchEvidenceLedgerV1 {
|
|
312
|
+
version: 1;
|
|
313
|
+
rootQuestion: string;
|
|
314
|
+
planId?: string;
|
|
315
|
+
snapshotId?: string;
|
|
316
|
+
entries: ResearchLedgerEntryV1[];
|
|
317
|
+
factIds: string[];
|
|
318
|
+
stoppingReason: 'completed' | 'budget' | 'insufficient_evidence' | 'blocked' | 'not_started';
|
|
319
|
+
}
|
|
320
|
+
export declare function capResearchBranches<T>(branches: T[], max?: number): T[];
|
|
321
|
+
export declare function buildResearchEvidenceLedger(input: {
|
|
322
|
+
rootQuestion: string;
|
|
323
|
+
planId?: string;
|
|
324
|
+
snapshotId?: string;
|
|
325
|
+
entries: ResearchLedgerEntryV1[];
|
|
326
|
+
stoppingReason?: ResearchEvidenceLedgerV1['stoppingReason'];
|
|
327
|
+
}): ResearchEvidenceLedgerV1;
|
|
328
|
+
/** The only accepted host-side execution identity is a SHA-256 fingerprint. */
|
|
329
|
+
export declare function normalizeAnalyticalExecutionFingerprint(value: unknown): string | undefined;
|
|
330
|
+
/**
|
|
331
|
+
* Normalize a complete DQL execution receipt. A partial object or arbitrary
|
|
332
|
+
* identifier is deliberately not execution evidence.
|
|
333
|
+
*/
|
|
334
|
+
export declare function normalizeAnalyticalExecutionReceipt(value: unknown): DqlArtifactExecutionReceipt | undefined;
|
|
335
|
+
export declare function buildCoverageGap(input: Omit<AnalyticalCoverageGapV1, 'version'>): AnalyticalCoverageGapV1;
|
|
336
|
+
//# sourceMappingURL=analytical-orchestration.d.ts.map
|