@duckcodeailabs/dql-agent 1.11.10 → 1.12.0
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.map +1 -1
- package/dist/agent-run-engine.js +7 -3
- package/dist/agent-run-engine.js.map +1 -1
- package/dist/answer-loop.d.ts +25 -1
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +139 -16
- package/dist/answer-loop.js.map +1 -1
- package/dist/conversation/rolling-summary.d.ts +23 -0
- package/dist/conversation/rolling-summary.d.ts.map +1 -1
- package/dist/conversation/rolling-summary.js +64 -0
- package/dist/conversation/rolling-summary.js.map +1 -1
- package/dist/conversation/session-store.d.ts +18 -2
- package/dist/conversation/session-store.d.ts.map +1 -1
- package/dist/conversation/session-store.js +65 -8
- package/dist/conversation/session-store.js.map +1 -1
- package/dist/conversation/snapshot.d.ts +37 -4
- package/dist/conversation/snapshot.d.ts.map +1 -1
- package/dist/conversation/snapshot.js +115 -6
- package/dist/conversation/snapshot.js.map +1 -1
- package/dist/hints/correction-eval.d.ts.map +1 -1
- package/dist/hints/correction-eval.js +4 -6
- package/dist/hints/correction-eval.js.map +1 -1
- package/dist/hints/dependencies.d.ts +63 -0
- package/dist/hints/dependencies.d.ts.map +1 -0
- package/dist/hints/dependencies.js +196 -0
- package/dist/hints/dependencies.js.map +1 -0
- package/dist/hints/git-store.d.ts +55 -2
- package/dist/hints/git-store.d.ts.map +1 -1
- package/dist/hints/git-store.js +246 -11
- package/dist/hints/git-store.js.map +1 -1
- package/dist/hints/graph.d.ts +17 -0
- package/dist/hints/graph.d.ts.map +1 -0
- package/dist/hints/graph.js +222 -0
- package/dist/hints/graph.js.map +1 -0
- package/dist/hints/lifecycle.d.ts +101 -0
- package/dist/hints/lifecycle.d.ts.map +1 -0
- package/dist/hints/lifecycle.js +387 -0
- package/dist/hints/lifecycle.js.map +1 -0
- package/dist/hints/retrieval.d.ts +13 -1
- package/dist/hints/retrieval.d.ts.map +1 -1
- package/dist/hints/retrieval.js +74 -11
- package/dist/hints/retrieval.js.map +1 -1
- package/dist/hints/store.d.ts +9 -2
- package/dist/hints/store.d.ts.map +1 -1
- package/dist/hints/store.js +155 -15
- package/dist/hints/store.js.map +1 -1
- package/dist/hints/types.d.ts +63 -3
- package/dist/hints/types.d.ts.map +1 -1
- package/dist/hints/types.js +1 -1
- package/dist/hints/types.js.map +1 -1
- package/dist/index.d.ts +16 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/intent-controller.d.ts.map +1 -1
- package/dist/intent-controller.js +24 -3
- package/dist/intent-controller.js.map +1 -1
- package/dist/metadata/catalog.d.ts +32 -0
- package/dist/metadata/catalog.d.ts.map +1 -1
- package/dist/metadata/catalog.js +86 -4
- package/dist/metadata/catalog.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +32 -9
- package/dist/router.js.map +1 -1
- package/dist/skills/loader.js +1 -1
- package/dist/skills/loader.js.map +1 -1
- package/dist/tools/registry.js +5 -5
- package/dist/tools/registry.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { buildLocalContextPack } from '../metadata/catalog.js';
|
|
3
|
+
import { validateSqlAgainstLocalContext } from '../metadata/sql-context-validation.js';
|
|
4
|
+
import { evaluateHint, getCorrectionTraceFromGit, getHintEvaluationFromGit, getHintFromGit, HintLifecycleError, recordCorrectionTrace, reopenHint, requiresEvaluatedApproval, reviewHint, updateHintCandidate, } from './git-store.js';
|
|
5
|
+
import { assessHintFreshness, collectHintDependencies } from './dependencies.js';
|
|
6
|
+
/**
|
|
7
|
+
* Shared correction capture path for the notebook API, CLI runtime, and MCP.
|
|
8
|
+
* Capture remains permissive: unsafe or unresolved corrections are retained as
|
|
9
|
+
* candidates with lifecycle errors, but can never pass approval.
|
|
10
|
+
*/
|
|
11
|
+
export async function recordGovernedCorrection(projectRoot, input, resolveContext = resolveGovernedHintContext) {
|
|
12
|
+
const context = await resolveContext({
|
|
13
|
+
projectRoot,
|
|
14
|
+
question: input.question,
|
|
15
|
+
correctedSql: input.correctedSql,
|
|
16
|
+
scope: input.scope,
|
|
17
|
+
snapshotId: input.snapshotId,
|
|
18
|
+
}).catch((error) => unresolvedContext(input, error));
|
|
19
|
+
const lifecycleErrors = failuresFromChecks(context.checks);
|
|
20
|
+
const requiredEvaluation = input.requiredEvaluation?.trim()
|
|
21
|
+
|| `correction: ${input.question.trim().replace(/\s+/g, ' ').slice(0, 60)}`;
|
|
22
|
+
const evidence = uniqueStrings([
|
|
23
|
+
...(input.evidence ?? []),
|
|
24
|
+
`question: ${input.question}`,
|
|
25
|
+
...(input.correctedSql ? [`corrected SQL: ${compact(input.correctedSql, 400)}`] : []),
|
|
26
|
+
...context.evidence,
|
|
27
|
+
]);
|
|
28
|
+
return recordCorrectionTrace(projectRoot, {
|
|
29
|
+
...input,
|
|
30
|
+
failedRoute: input.failedRoute?.trim() || 'generated_answer',
|
|
31
|
+
evidence,
|
|
32
|
+
snapshotId: context.snapshotId,
|
|
33
|
+
requiredEvaluation,
|
|
34
|
+
dependencies: context.dependencies,
|
|
35
|
+
lifecycleErrors,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Shared fail-closed review path. A v3 approval always creates a fresh
|
|
40
|
+
* evaluation artifact, so a failed attempt remains reviewable and retryable.
|
|
41
|
+
*/
|
|
42
|
+
export async function reviewGovernedHint(projectRoot, input) {
|
|
43
|
+
const hint = getHintFromGit(projectRoot, input.hintId);
|
|
44
|
+
if (!hint)
|
|
45
|
+
return null;
|
|
46
|
+
if (input.decision === 'rejected' || !requiresEvaluatedApproval(projectRoot)) {
|
|
47
|
+
return reviewHint(projectRoot, {
|
|
48
|
+
hintId: input.hintId,
|
|
49
|
+
decision: input.decision,
|
|
50
|
+
reviewer: input.reviewer,
|
|
51
|
+
note: input.note,
|
|
52
|
+
snapshotId: input.snapshotId,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (hint.status !== 'candidate') {
|
|
56
|
+
throw new HintLifecycleError('HINT_NOT_CANDIDATE', `Hint ${hint.id} is ${hint.status}; only candidates can be reviewed.`);
|
|
57
|
+
}
|
|
58
|
+
if (!hint.correctedSql?.trim()) {
|
|
59
|
+
throw new HintLifecycleError('HINT_CORRECTED_SQL_REQUIRED', `Hint ${hint.id} cannot be approved without corrected SQL.`);
|
|
60
|
+
}
|
|
61
|
+
if (!hint.requiredEvaluation || !hint.snapshotId) {
|
|
62
|
+
throw new HintLifecycleError('HINT_PROVENANCE_REQUIRED', `Hint ${hint.id} is missing its required evaluation or immutable snapshot.`);
|
|
63
|
+
}
|
|
64
|
+
const trace = hint.traceId ? getCorrectionTraceFromGit(projectRoot, hint.traceId) : null;
|
|
65
|
+
const question = trace?.question?.trim() || hint.title;
|
|
66
|
+
const resolveContext = input.resolveContext ?? resolveGovernedHintContext;
|
|
67
|
+
const current = await resolveContext({
|
|
68
|
+
projectRoot,
|
|
69
|
+
question,
|
|
70
|
+
correctedSql: hint.correctedSql,
|
|
71
|
+
scope: hint.scope,
|
|
72
|
+
snapshotId: input.snapshotId,
|
|
73
|
+
}).catch((error) => unresolvedContext({ question, scope: hint.scope, correctedSql: hint.correctedSql }, error));
|
|
74
|
+
const freshness = assessHintFreshness({
|
|
75
|
+
dependencies: hint.dependencies,
|
|
76
|
+
snapshotId: hint.snapshotId,
|
|
77
|
+
currentSnapshotId: current.snapshotId,
|
|
78
|
+
currentDependencies: new Map(current.dependencies.map((dependency) => [dependency.id, dependency.fingerprint])),
|
|
79
|
+
});
|
|
80
|
+
const checks = [
|
|
81
|
+
...current.checks,
|
|
82
|
+
{
|
|
83
|
+
name: 'snapshot-current',
|
|
84
|
+
passed: freshness.current,
|
|
85
|
+
evidence: freshness.snapshotCurrent
|
|
86
|
+
? `Current snapshot matches ${hint.snapshotId}.`
|
|
87
|
+
: freshness.dependenciesCurrent
|
|
88
|
+
? `Project snapshot changed from ${hint.snapshotId} to ${current.snapshotId}, but every scoped dependency still matches.`
|
|
89
|
+
: `Candidate snapshot ${hint.snapshotId}; current snapshot ${current.snapshotId}.`,
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
checks.push({
|
|
93
|
+
name: 'dependencies-current',
|
|
94
|
+
passed: freshness.dependenciesCurrent,
|
|
95
|
+
evidence: freshness.staleDependencies.length > 0
|
|
96
|
+
? `Changed or missing dependencies: ${freshness.staleDependencies.map((dependency) => dependency.id).join(', ')}.`
|
|
97
|
+
: `${hint.dependencies?.length ?? 0} recorded dependencies match current governed context.`,
|
|
98
|
+
});
|
|
99
|
+
const rowLimit = clampRowLimit(input.rowLimit);
|
|
100
|
+
const executionEvidence = [];
|
|
101
|
+
if (input.executeSql) {
|
|
102
|
+
try {
|
|
103
|
+
const result = await input.executeSql(hint.correctedSql, { rowLimit, question });
|
|
104
|
+
const bounded = Number.isInteger(result.rowCount)
|
|
105
|
+
&& result.rowCount >= 0
|
|
106
|
+
&& result.rowCount <= rowLimit
|
|
107
|
+
&& Array.isArray(result.rows)
|
|
108
|
+
&& result.rows.length <= rowLimit;
|
|
109
|
+
checks.push({
|
|
110
|
+
name: 'bounded-execution',
|
|
111
|
+
passed: bounded,
|
|
112
|
+
evidence: bounded
|
|
113
|
+
? `Compiled and executed read-only SQL with ${result.rowCount} row(s), bounded to ${rowLimit}.`
|
|
114
|
+
: `Execution returned an invalid or unbounded result (rowCount=${String(result.rowCount)}, rows=${result.rows?.length ?? 'unknown'}).`,
|
|
115
|
+
});
|
|
116
|
+
const hasResultShape = Array.isArray(result.columns) && result.columns.length > 0;
|
|
117
|
+
checks.push({
|
|
118
|
+
name: 'result-shape-assertion',
|
|
119
|
+
passed: hasResultShape,
|
|
120
|
+
evidence: hasResultShape
|
|
121
|
+
? `Result columns: ${result.columns.map((column) => typeof column === 'string'
|
|
122
|
+
? column
|
|
123
|
+
: column && typeof column === 'object' && 'name' in column
|
|
124
|
+
? String(column.name ?? '?')
|
|
125
|
+
: '?').join(', ')}.`
|
|
126
|
+
: 'Execution returned no inspectable result columns.',
|
|
127
|
+
});
|
|
128
|
+
executionEvidence.push(`bounded result: rows=${result.rowCount}; columns=${result.columns.length}; limit=${rowLimit}`);
|
|
129
|
+
if (result.executionReceipt) {
|
|
130
|
+
executionEvidence.push(`execution receipt: ${compact(JSON.stringify(result.executionReceipt), 500)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
checks.push({
|
|
135
|
+
name: 'bounded-execution',
|
|
136
|
+
passed: false,
|
|
137
|
+
evidence: error instanceof Error ? error.message : String(error),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
checks.push({
|
|
143
|
+
name: 'review-evidence-assertion',
|
|
144
|
+
passed: Boolean(input.note?.trim()),
|
|
145
|
+
evidence: input.note?.trim()
|
|
146
|
+
? `Reviewer assertion: ${compact(input.note, 300)}`
|
|
147
|
+
: 'This surface cannot execute the correction; an explicit reviewer evidence note is required.',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
checks.push({
|
|
151
|
+
name: 'human-semantic-approval',
|
|
152
|
+
passed: Boolean(input.reviewer.trim()),
|
|
153
|
+
evidence: `Explicit approval by ${input.reviewer.trim() || 'unknown reviewer'}; execution success alone does not establish semantic correctness.`,
|
|
154
|
+
});
|
|
155
|
+
const evaluated = evaluateHint(projectRoot, {
|
|
156
|
+
hintId: hint.id,
|
|
157
|
+
snapshotId: hint.snapshotId,
|
|
158
|
+
evaluation: hint.requiredEvaluation,
|
|
159
|
+
evaluator: input.reviewer,
|
|
160
|
+
checks,
|
|
161
|
+
evidence: uniqueStrings([
|
|
162
|
+
`candidate snapshot: ${hint.snapshotId}`,
|
|
163
|
+
`current snapshot: ${current.snapshotId}`,
|
|
164
|
+
...current.evidence,
|
|
165
|
+
...executionEvidence,
|
|
166
|
+
]),
|
|
167
|
+
note: input.note,
|
|
168
|
+
});
|
|
169
|
+
if (evaluated.evaluation.status !== 'passed') {
|
|
170
|
+
throw new HintLifecycleError('HINT_EVALUATION_FAILED', `Hint ${hint.id} remains a candidate because evaluation ${evaluated.evaluation.id} failed: ${checks.filter((check) => !check.passed).map((check) => check.name).join(', ')}. The evaluation is persisted and may be rerun after correction.`);
|
|
171
|
+
}
|
|
172
|
+
const reviewed = reviewHint(projectRoot, {
|
|
173
|
+
hintId: hint.id,
|
|
174
|
+
decision: 'approved',
|
|
175
|
+
reviewer: input.reviewer,
|
|
176
|
+
note: input.note,
|
|
177
|
+
snapshotId: hint.snapshotId,
|
|
178
|
+
});
|
|
179
|
+
return reviewed ? { ...reviewed, evaluation: evaluated.evaluation } : null;
|
|
180
|
+
}
|
|
181
|
+
/** CTX-005 / API-003: read-only live inspection used by review surfaces and lifecycle decisions. */
|
|
182
|
+
export async function inspectGovernedHint(projectRoot, input) {
|
|
183
|
+
const hint = getHintFromGit(projectRoot, input.hintId);
|
|
184
|
+
if (!hint)
|
|
185
|
+
return null;
|
|
186
|
+
const trace = hint.traceId ? getCorrectionTraceFromGit(projectRoot, hint.traceId) ?? undefined : undefined;
|
|
187
|
+
const question = trace?.question?.trim() || hint.title;
|
|
188
|
+
const resolveContext = input.resolveContext ?? resolveGovernedHintContext;
|
|
189
|
+
const current = await resolveContext({
|
|
190
|
+
projectRoot,
|
|
191
|
+
question,
|
|
192
|
+
correctedSql: hint.correctedSql,
|
|
193
|
+
scope: hint.scope,
|
|
194
|
+
snapshotId: input.snapshotId,
|
|
195
|
+
}).catch((error) => unresolvedContext({ question, scope: hint.scope, correctedSql: hint.correctedSql }, error));
|
|
196
|
+
const freshness = assessHintFreshness({
|
|
197
|
+
dependencies: hint.dependencies,
|
|
198
|
+
snapshotId: hint.snapshotId,
|
|
199
|
+
currentSnapshotId: current.snapshotId,
|
|
200
|
+
currentDependencies: new Map(current.dependencies.map((dependency) => [dependency.id, dependency.fingerprint])),
|
|
201
|
+
});
|
|
202
|
+
const checks = [
|
|
203
|
+
...current.checks,
|
|
204
|
+
{
|
|
205
|
+
name: 'snapshot-current',
|
|
206
|
+
passed: freshness.current,
|
|
207
|
+
evidence: freshness.snapshotCurrent
|
|
208
|
+
? `Current snapshot matches ${hint.snapshotId}.`
|
|
209
|
+
: freshness.dependenciesCurrent
|
|
210
|
+
? `Project snapshot changed from ${hint.snapshotId ?? '(missing)'} to ${current.snapshotId}, but every scoped dependency still matches.`
|
|
211
|
+
: `Recorded snapshot ${hint.snapshotId ?? '(missing)'}; current snapshot ${current.snapshotId}.`,
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: 'dependencies-current',
|
|
215
|
+
passed: freshness.dependenciesCurrent,
|
|
216
|
+
evidence: freshness.staleDependencies.length > 0
|
|
217
|
+
? `Changed or missing dependencies: ${freshness.staleDependencies.map((dependency) => dependency.id).join(', ')}.`
|
|
218
|
+
: `${hint.dependencies?.length ?? 0} recorded dependencies match current governed context.`,
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
const state = current.snapshotId.startsWith('unverified:')
|
|
222
|
+
? 'unverified'
|
|
223
|
+
: !freshness.current
|
|
224
|
+
? 'stale'
|
|
225
|
+
: checks.some((check) => !check.passed)
|
|
226
|
+
? 'invalid'
|
|
227
|
+
: 'current';
|
|
228
|
+
return {
|
|
229
|
+
hint,
|
|
230
|
+
trace,
|
|
231
|
+
evaluation: hint.evaluationId ? getHintEvaluationFromGit(projectRoot, hint.evaluationId) ?? undefined : undefined,
|
|
232
|
+
currentSnapshotId: current.snapshotId,
|
|
233
|
+
snapshotCurrent: freshness.snapshotCurrent,
|
|
234
|
+
dependenciesCurrent: freshness.dependenciesCurrent,
|
|
235
|
+
driftedDependencies: freshness.staleDependencies,
|
|
236
|
+
checks,
|
|
237
|
+
state,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/** CTX-005 / E2E-001: explicit edit revalidates provenance and clears prior evaluation state. */
|
|
241
|
+
export async function editGovernedHintCandidate(projectRoot, input) {
|
|
242
|
+
const hint = getHintFromGit(projectRoot, input.hintId);
|
|
243
|
+
if (!hint)
|
|
244
|
+
return null;
|
|
245
|
+
const trace = hint.traceId ? getCorrectionTraceFromGit(projectRoot, hint.traceId) : null;
|
|
246
|
+
const scope = input.scope ?? hint.scope;
|
|
247
|
+
const correctedSql = input.correctedSql?.trim() || hint.correctedSql;
|
|
248
|
+
const question = trace?.question?.trim() || input.title?.trim() || hint.title;
|
|
249
|
+
const resolveContext = input.resolveContext ?? resolveGovernedHintContext;
|
|
250
|
+
const current = await resolveContext({
|
|
251
|
+
projectRoot,
|
|
252
|
+
question,
|
|
253
|
+
correctedSql,
|
|
254
|
+
scope,
|
|
255
|
+
snapshotId: input.snapshotId,
|
|
256
|
+
}).catch((error) => unresolvedContext({ question, scope, correctedSql }, error));
|
|
257
|
+
return updateHintCandidate(projectRoot, {
|
|
258
|
+
hintId: hint.id,
|
|
259
|
+
title: input.title,
|
|
260
|
+
guidance: input.guidance,
|
|
261
|
+
correctedSql,
|
|
262
|
+
scope,
|
|
263
|
+
snapshotId: current.snapshotId,
|
|
264
|
+
dependencies: current.dependencies,
|
|
265
|
+
lifecycleErrors: failuresFromChecks(current.checks),
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/** CTX-005: reopen an applied/retired hint as a non-retrievable candidate against current context. */
|
|
269
|
+
export async function reopenGovernedHint(projectRoot, input) {
|
|
270
|
+
const hint = getHintFromGit(projectRoot, input.hintId);
|
|
271
|
+
if (!hint)
|
|
272
|
+
return null;
|
|
273
|
+
const trace = hint.traceId ? getCorrectionTraceFromGit(projectRoot, hint.traceId) : null;
|
|
274
|
+
const question = trace?.question?.trim() || hint.title;
|
|
275
|
+
const resolveContext = input.resolveContext ?? resolveGovernedHintContext;
|
|
276
|
+
const current = await resolveContext({
|
|
277
|
+
projectRoot,
|
|
278
|
+
question,
|
|
279
|
+
correctedSql: hint.correctedSql,
|
|
280
|
+
scope: hint.scope,
|
|
281
|
+
snapshotId: input.snapshotId,
|
|
282
|
+
}).catch((error) => unresolvedContext({ question, scope: hint.scope, correctedSql: hint.correctedSql }, error));
|
|
283
|
+
return reopenHint(projectRoot, {
|
|
284
|
+
hintId: hint.id,
|
|
285
|
+
reviewer: input.reviewer,
|
|
286
|
+
note: input.note,
|
|
287
|
+
snapshotId: current.snapshotId,
|
|
288
|
+
dependencies: current.dependencies,
|
|
289
|
+
lifecycleErrors: failuresFromChecks(current.checks),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
/** Resolve current SQL authorization and content-addressed dependencies. */
|
|
293
|
+
export async function resolveGovernedHintContext(input) {
|
|
294
|
+
const pack = await buildLocalContextPack(input.projectRoot, {
|
|
295
|
+
question: input.question,
|
|
296
|
+
surface: 'hint_lifecycle',
|
|
297
|
+
strictness: 'safe',
|
|
298
|
+
});
|
|
299
|
+
const snapshotId = input.snapshotId?.trim()
|
|
300
|
+
|| pack.freshness.fingerprint
|
|
301
|
+
|| `unverified:${shortHash(`${input.question}\0${input.correctedSql ?? ''}`)}`;
|
|
302
|
+
const collected = collectHintDependencies({
|
|
303
|
+
sql: input.correctedSql,
|
|
304
|
+
scope: input.scope,
|
|
305
|
+
objects: pack.objects,
|
|
306
|
+
relations: pack.allowedSqlContext.relations,
|
|
307
|
+
fallbackFingerprint: pack.freshness.fingerprint ?? undefined,
|
|
308
|
+
});
|
|
309
|
+
const validation = input.correctedSql?.trim()
|
|
310
|
+
? validateSqlAgainstLocalContext(input.correctedSql, pack, {
|
|
311
|
+
dialect: input.scope.dialect,
|
|
312
|
+
question: input.question,
|
|
313
|
+
})
|
|
314
|
+
: null;
|
|
315
|
+
const checks = [
|
|
316
|
+
{
|
|
317
|
+
name: 'corrected-sql-present',
|
|
318
|
+
passed: Boolean(input.correctedSql?.trim()),
|
|
319
|
+
evidence: input.correctedSql?.trim() ? 'Candidate includes corrected SQL.' : 'Candidate has no corrected SQL.',
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
name: 'read-only-sql',
|
|
323
|
+
passed: Boolean(validation && (validation.ok
|
|
324
|
+
|| (validation.code !== 'unsafe_sql' && validation.code !== 'insufficient_context'))),
|
|
325
|
+
evidence: validation?.ok
|
|
326
|
+
? 'Parser accepted a read-only SELECT/WITH statement.'
|
|
327
|
+
: validation?.error ?? 'No SQL was available to parse.',
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: 'relations-authorized',
|
|
331
|
+
passed: Boolean(validation?.ok) && collected.referencedRelations.length > 0 && collected.unknownRelations.length === 0,
|
|
332
|
+
evidence: collected.unknownRelations.length > 0
|
|
333
|
+
? `Relations outside current governed context: ${collected.unknownRelations.join(', ')}.`
|
|
334
|
+
: collected.referencedRelations.length > 0
|
|
335
|
+
? `Authorized relations: ${collected.referencedRelations.join(', ')}.`
|
|
336
|
+
: validation && !validation.ok
|
|
337
|
+
? validation.error
|
|
338
|
+
: 'No governed relation was referenced.',
|
|
339
|
+
},
|
|
340
|
+
];
|
|
341
|
+
return {
|
|
342
|
+
snapshotId,
|
|
343
|
+
dependencies: collected.dependencies,
|
|
344
|
+
checks,
|
|
345
|
+
evidence: [
|
|
346
|
+
`snapshot: ${snapshotId}`,
|
|
347
|
+
...collected.dependencies.map((dependency) => `dependency: ${dependency.id}@${dependency.fingerprint}`),
|
|
348
|
+
],
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function unresolvedContext(input, error) {
|
|
352
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
353
|
+
return {
|
|
354
|
+
snapshotId: `unverified:${shortHash(`${input.question}\0${input.correctedSql ?? ''}`)}`,
|
|
355
|
+
dependencies: [],
|
|
356
|
+
checks: [
|
|
357
|
+
{ name: 'context-resolved', passed: false, evidence: message },
|
|
358
|
+
{ name: 'relations-authorized', passed: false, evidence: 'Current governed context could not be resolved.' },
|
|
359
|
+
],
|
|
360
|
+
evidence: [`context resolution failed: ${message}`],
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
function failuresFromChecks(checks) {
|
|
364
|
+
const at = new Date().toISOString();
|
|
365
|
+
return checks
|
|
366
|
+
.filter((check) => !check.passed)
|
|
367
|
+
.map((check) => ({
|
|
368
|
+
code: `HINT_${check.name.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}_FAILED`,
|
|
369
|
+
message: check.evidence || `${check.name} failed.`,
|
|
370
|
+
at,
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
function uniqueStrings(values) {
|
|
374
|
+
return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
|
|
375
|
+
}
|
|
376
|
+
function compact(value, limit) {
|
|
377
|
+
return value.replace(/\s+/g, ' ').trim().slice(0, limit);
|
|
378
|
+
}
|
|
379
|
+
function shortHash(value) {
|
|
380
|
+
return createHash('sha256').update(value).digest('hex').slice(0, 16);
|
|
381
|
+
}
|
|
382
|
+
function clampRowLimit(value) {
|
|
383
|
+
if (!Number.isFinite(value))
|
|
384
|
+
return 200;
|
|
385
|
+
return Math.max(1, Math.min(500, Math.floor(value)));
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/hints/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
* ever returned in normal mode. A hint is applied only within its declared
|
|
9
9
|
* scope (metric / dbt model / domain / dialect / term / block).
|
|
10
10
|
*/
|
|
11
|
-
import type
|
|
11
|
+
import { type QuestionScope } from './types.js';
|
|
12
12
|
import type { EmbeddingProvider } from '../embeddings/provider.js';
|
|
13
13
|
export interface AppliedHint {
|
|
14
14
|
hintId: string;
|
|
15
15
|
title: string;
|
|
16
16
|
guidance: string;
|
|
17
17
|
scopeReason: string;
|
|
18
|
+
graphReason?: string;
|
|
18
19
|
score: number;
|
|
19
20
|
correctedSql?: string;
|
|
20
21
|
traceId?: string;
|
|
@@ -28,6 +29,13 @@ export interface HintRetrievalResult {
|
|
|
28
29
|
titles: [string, string];
|
|
29
30
|
reason: string;
|
|
30
31
|
}>;
|
|
32
|
+
/** Approved hints withheld by governance gates, retained for review/repair. */
|
|
33
|
+
excluded: Array<{
|
|
34
|
+
hintId: string;
|
|
35
|
+
title: string;
|
|
36
|
+
reason: 'stale' | 'superseded' | 'conflict';
|
|
37
|
+
detail: string;
|
|
38
|
+
}>;
|
|
31
39
|
}
|
|
32
40
|
export interface RetrieveScopedHintsOptions {
|
|
33
41
|
questionScope: QuestionScope;
|
|
@@ -39,6 +47,10 @@ export interface RetrieveScopedHintsOptions {
|
|
|
39
47
|
alpha?: number;
|
|
40
48
|
embeddingProvider?: EmbeddingProvider;
|
|
41
49
|
indexPath?: string;
|
|
50
|
+
/** Current content fingerprints keyed by persisted dependency id. */
|
|
51
|
+
currentDependencies?: ReadonlyMap<string, string>;
|
|
52
|
+
/** Conservative fallback for older v3 hints without dependency provenance. */
|
|
53
|
+
currentSnapshotId?: string | null;
|
|
42
54
|
}
|
|
43
55
|
/**
|
|
44
56
|
* Retrieve approved scoped hints from the SQLite index. Returns an empty result
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retrieval.d.ts","sourceRoot":"","sources":["../../src/hints/retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"retrieval.d.ts","sourceRoot":"","sources":["../../src/hints/retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAA4B,KAAK,aAAa,EAAwB,MAAM,YAAY,CAAC;AAEhG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,qEAAqE;IACrE,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,8EAA8E;IAC9E,SAAS,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1F,+EAA+E;IAC/E,QAAQ,EAAE,KAAK,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,OAAO,GAAG,YAAY,GAAG,UAAU,CAAC;QAC5C,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAyF9B"}
|
package/dist/hints/retrieval.js
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import { existsSync } from 'node:fs';
|
|
12
12
|
import { defaultHintIndexPath } from './git-store.js';
|
|
13
13
|
import { HintStore } from './store.js';
|
|
14
|
+
import { hintsConflict } from './types.js';
|
|
15
|
+
import { assessHintFreshness } from './dependencies.js';
|
|
14
16
|
/**
|
|
15
17
|
* Retrieve approved scoped hints from the SQLite index. Returns an empty result
|
|
16
18
|
* (no error) when the index does not exist yet or no hints match — keeping the
|
|
@@ -19,7 +21,7 @@ import { HintStore } from './store.js';
|
|
|
19
21
|
export async function retrieveScopedHints(projectRoot, options) {
|
|
20
22
|
const indexPath = options.indexPath ?? defaultHintIndexPath(projectRoot);
|
|
21
23
|
if (!existsSync(indexPath))
|
|
22
|
-
return { applied: [], conflicts: [] };
|
|
24
|
+
return { applied: [], conflicts: [], excluded: [] };
|
|
23
25
|
const store = new HintStore(indexPath);
|
|
24
26
|
try {
|
|
25
27
|
const matches = await store.searchApprovedHints({
|
|
@@ -28,19 +30,79 @@ export async function retrieveScopedHints(projectRoot, options) {
|
|
|
28
30
|
alpha: options.alpha,
|
|
29
31
|
embeddingProvider: options.embeddingProvider,
|
|
30
32
|
});
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
const excluded = [];
|
|
34
|
+
const fresh = matches.filter((match) => {
|
|
35
|
+
const currentDependencies = new Map(options.currentDependencies ?? []);
|
|
36
|
+
if (options.currentSnapshotId) {
|
|
37
|
+
for (const dependency of match.hint.dependencies ?? []) {
|
|
38
|
+
if (dependency.id.startsWith('scope:')) {
|
|
39
|
+
currentDependencies.set(dependency.id, options.currentSnapshotId);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const freshness = assessHintFreshness({
|
|
44
|
+
dependencies: match.hint.dependencies,
|
|
45
|
+
snapshotId: match.hint.snapshotId,
|
|
46
|
+
currentDependencies,
|
|
47
|
+
currentSnapshotId: options.currentSnapshotId,
|
|
48
|
+
});
|
|
49
|
+
if (freshness.current)
|
|
50
|
+
return true;
|
|
51
|
+
excluded.push({
|
|
52
|
+
hintId: match.hint.id,
|
|
53
|
+
title: match.hint.title,
|
|
54
|
+
reason: 'stale',
|
|
55
|
+
detail: freshness.staleDependencies.length > 0
|
|
56
|
+
? `Changed or missing dependencies: ${freshness.staleDependencies.map((dependency) => dependency.id).join(', ')}.`
|
|
57
|
+
: `Candidate snapshot ${match.hint.snapshotId} differs from current snapshot ${options.currentSnapshotId}.`,
|
|
58
|
+
});
|
|
59
|
+
return false;
|
|
60
|
+
});
|
|
61
|
+
const eligibleIds = new Set(fresh.map((match) => match.hint.id));
|
|
62
|
+
const supersededIds = new Set(fresh
|
|
63
|
+
.map((match) => match.hint.supersedes)
|
|
64
|
+
.filter((id) => Boolean(id) && eligibleIds.has(id)));
|
|
65
|
+
const unsuperseded = fresh.filter((match) => {
|
|
66
|
+
if (!supersededIds.has(match.hint.id))
|
|
67
|
+
return true;
|
|
68
|
+
excluded.push({
|
|
69
|
+
hintId: match.hint.id,
|
|
70
|
+
title: match.hint.title,
|
|
71
|
+
reason: 'superseded',
|
|
72
|
+
detail: 'A newer eligible approved hint explicitly supersedes this hint.',
|
|
73
|
+
});
|
|
74
|
+
return false;
|
|
75
|
+
});
|
|
76
|
+
const conflictPairs = [];
|
|
77
|
+
for (let left = 0; left < unsuperseded.length; left += 1) {
|
|
78
|
+
for (let right = left + 1; right < unsuperseded.length; right += 1) {
|
|
79
|
+
const a = unsuperseded[left].hint;
|
|
80
|
+
const b = unsuperseded[right].hint;
|
|
81
|
+
if (hintsConflict(a, b))
|
|
82
|
+
conflictPairs.push([a, b]);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const conflictingIds = new Set(conflictPairs.flatMap(([a, b]) => [a.id, b.id]));
|
|
86
|
+
for (const match of unsuperseded) {
|
|
87
|
+
if (!conflictingIds.has(match.hint.id))
|
|
88
|
+
continue;
|
|
89
|
+
excluded.push({
|
|
90
|
+
hintId: match.hint.id,
|
|
91
|
+
title: match.hint.title,
|
|
92
|
+
reason: 'conflict',
|
|
93
|
+
detail: 'Overlapping approved hints are withheld until one explicitly supersedes the other.',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const applied = unsuperseded
|
|
97
|
+
.filter((match) => !conflictingIds.has(match.hint.id))
|
|
98
|
+
.slice(0, options.limit ?? 6)
|
|
99
|
+
.map(toAppliedHint);
|
|
100
|
+
const conflicts = conflictPairs.map(([a, b]) => ({
|
|
39
101
|
hintIds: [a.id, b.id],
|
|
40
102
|
titles: [a.title, b.title],
|
|
41
|
-
reason: `Approved hints "${a.title}" and "${b.title}" overlap on scope and
|
|
103
|
+
reason: `Approved hints "${a.title}" and "${b.title}" overlap on scope and are withheld until review resolves the conflict.`,
|
|
42
104
|
}));
|
|
43
|
-
return { applied, conflicts };
|
|
105
|
+
return { applied, conflicts, excluded };
|
|
44
106
|
}
|
|
45
107
|
finally {
|
|
46
108
|
store.close();
|
|
@@ -52,6 +114,7 @@ function toAppliedHint(match) {
|
|
|
52
114
|
title: match.hint.title,
|
|
53
115
|
guidance: match.hint.guidance,
|
|
54
116
|
scopeReason: match.scopeReason,
|
|
117
|
+
graphReason: match.graphReason,
|
|
55
118
|
score: match.score,
|
|
56
119
|
correctedSql: match.hint.correctedSql,
|
|
57
120
|
traceId: match.hint.traceId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retrieval.js","sourceRoot":"","sources":["../../src/hints/retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"retrieval.js","sourceRoot":"","sources":["../../src/hints/retrieval.ts"],"names":[],"mappings":"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"}
|
package/dist/hints/store.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* extending the existing store rather than introducing a second cache file.
|
|
7
7
|
* Approved-only is enforced at the retrieval boundary (`searchApprovedHints`).
|
|
8
8
|
*/
|
|
9
|
-
import { type Hint, type HintStatus, type QuestionScope, type ScopedHintMatch } from './types.js';
|
|
9
|
+
import { type Hint, type HintGraphEdge, type HintStatus, type QuestionScope, type ScopedHintMatch } from './types.js';
|
|
10
10
|
import { type EmbeddingProvider } from '../embeddings/provider.js';
|
|
11
11
|
export interface SearchApprovedHintsOptions {
|
|
12
12
|
questionScope: QuestionScope;
|
|
@@ -19,19 +19,26 @@ export declare class HintStore {
|
|
|
19
19
|
private db;
|
|
20
20
|
constructor(dbPath: string);
|
|
21
21
|
private initSchema;
|
|
22
|
+
private ensureColumn;
|
|
22
23
|
/** Replace the whole index from the Git-authoritative hint set. */
|
|
23
|
-
rebuild(hints: Hint[]): void;
|
|
24
|
+
rebuild(hints: Hint[], projectionFingerprint?: string): void;
|
|
24
25
|
/** Upsert a single hint (keeps Git + SQLite in sync after a record/approve). */
|
|
25
26
|
upsert(hint: Hint): void;
|
|
27
|
+
/** Fingerprint of the Git hint set and projection schema currently indexed. */
|
|
28
|
+
projectionFingerprint(): string | undefined;
|
|
26
29
|
private insertRow;
|
|
30
|
+
private prepareEdgeInsert;
|
|
27
31
|
get(id: string): Hint | null;
|
|
28
32
|
list(status?: HintStatus): Hint[];
|
|
33
|
+
/** Typed, rebuildable graph connections for review and retrieval ranking. */
|
|
34
|
+
edgesForHint(hintId: string): HintGraphEdge[];
|
|
29
35
|
/**
|
|
30
36
|
* Retrieve APPROVED hints that apply to a question's scope. This is the only
|
|
31
37
|
* retrieval entry point used outside review/dev mode — draft/candidate hints
|
|
32
38
|
* are never returned here.
|
|
33
39
|
*/
|
|
34
40
|
searchApprovedHints(options: SearchApprovedHintsOptions): Promise<ScopedHintMatch[]>;
|
|
41
|
+
private approvedHintsForTargets;
|
|
35
42
|
/** Approved hints whose scopes overlap (surfaced as conflicts for review). */
|
|
36
43
|
conflictingApprovedHints(): Array<[Hint, Hint]>;
|
|
37
44
|
close(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/hints/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAEL,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/hints/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,aAAa,EAElB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAQpB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AAWnC,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,EAAE,MAAM;IAQ1B,OAAO,CAAC,UAAU;IAuElB,OAAO,CAAC,YAAY;IAOpB,mEAAmE;IACnE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI;IAkC5D,gFAAgF;IAChF,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAuBxB,+EAA+E;IAC/E,qBAAqB,IAAI,MAAM,GAAG,SAAS;IAO3C,OAAO,CAAC,SAAS;IAqDjB,OAAO,CAAC,iBAAiB;IAQzB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAK5B,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,EAAE;IAOjC,6EAA6E;IAC7E,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE;IAU7C;;;;OAIG;IACG,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAmF1F,OAAO,CAAC,uBAAuB;IAe/B,8EAA8E;IAC9E,wBAAwB,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAc/C,KAAK,IAAI,IAAI;CAGd"}
|