@duckcodeailabs/dql-mcp 1.5.3 → 1.6.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/context.d.ts CHANGED
@@ -1,7 +1,13 @@
1
- import { SemanticLayer, LineageGraph, type DQLManifest } from '@duckcodeailabs/dql-core';
1
+ import { DataLexContractRegistry, SemanticLayer, LineageGraph, type DQLManifest } from '@duckcodeailabs/dql-core';
2
2
  export interface DQLContextOptions {
3
3
  projectRoot: string;
4
4
  dqlVersion?: string;
5
+ /**
6
+ * Optional override for the DataLex manifest path. Defaults to
7
+ * `<projectRoot>/datalex-manifest.json`. The registry is consulted by
8
+ * tools that enforce datalex_contract bindings (e.g. query-via-block).
9
+ */
10
+ datalexManifestPath?: string;
5
11
  }
6
12
  /**
7
13
  * Shared read-only view over a DQL project.
@@ -12,13 +18,23 @@ export interface DQLContextOptions {
12
18
  export declare class DQLContext {
13
19
  readonly projectRoot: string;
14
20
  private readonly dqlVersion;
21
+ private readonly datalexManifestPath;
15
22
  private _manifest;
16
23
  private _semanticLayer;
17
24
  private _lineage;
25
+ private _datalexRegistry;
18
26
  constructor(options: DQLContextOptions);
19
27
  get manifest(): DQLManifest;
20
28
  get semanticLayer(): SemanticLayer;
21
29
  get lineageGraph(): LineageGraph;
30
+ /**
31
+ * Lazily-loaded registry of DataLex contracts for enforcing
32
+ * `datalex_contract` references on certified blocks. Tools call
33
+ * `registry.isLoaded()` to check whether a manifest was found before
34
+ * gating on resolution; that lets MCP work in projects that haven't
35
+ * adopted DataLex yet.
36
+ */
37
+ get datalexRegistry(): DataLexContractRegistry;
22
38
  refresh(): void;
23
39
  }
24
40
  /** Walk up from `startDir` until a `dql.config.json` is found, else return `startDir`. */
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,aAAa,EAEb,YAAY,EACZ,KAAK,WAAW,EAIjB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAA6B;gBAEjC,OAAO,EAAE,iBAAiB;IAKtC,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAED,IAAI,aAAa,IAAI,aAAa,CAGjC;IAED,IAAI,YAAY,IAAI,YAAY,CAG/B;IAED,OAAO,IAAI,IAAI;CA4BhB;AA6BD,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,uBAAuB,EAGvB,aAAa,EAEb,YAAY,EACZ,KAAK,WAAW,EAIjB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,gBAAgB,CAAwC;gBAEpD,OAAO,EAAE,iBAAiB;IAOtC,IAAI,QAAQ,IAAI,WAAW,CAG1B;IAED,IAAI,aAAa,IAAI,aAAa,CAGjC;IAED,IAAI,YAAY,IAAI,YAAY,CAG/B;IAED;;;;;;OAMG;IACH,IAAI,eAAe,IAAI,uBAAuB,CAO7C;IAED,OAAO,IAAI,IAAI;CA6BhB;AA6BD,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQxD"}
package/dist/context.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { dirname, join, resolve } from 'node:path';
3
- import { buildManifest, loadProjectConfig, resolveDbtManifestPath, SemanticLayer, resolveSemanticLayerWithDiagnostics, LineageGraph, } from '@duckcodeailabs/dql-core';
3
+ import { buildManifest, DataLexContractRegistry, loadProjectConfig, resolveDbtManifestPath, SemanticLayer, resolveSemanticLayerWithDiagnostics, LineageGraph, } from '@duckcodeailabs/dql-core';
4
4
  /**
5
5
  * Shared read-only view over a DQL project.
6
6
  *
@@ -10,12 +10,16 @@ import { buildManifest, loadProjectConfig, resolveDbtManifestPath, SemanticLayer
10
10
  export class DQLContext {
11
11
  projectRoot;
12
12
  dqlVersion;
13
+ datalexManifestPath;
13
14
  _manifest = null;
14
15
  _semanticLayer = null;
15
16
  _lineage = null;
17
+ _datalexRegistry = null;
16
18
  constructor(options) {
17
19
  this.projectRoot = options.projectRoot;
18
20
  this.dqlVersion = options.dqlVersion ?? 'mcp';
21
+ this.datalexManifestPath =
22
+ options.datalexManifestPath ?? join(options.projectRoot, 'datalex-manifest.json');
19
23
  }
20
24
  get manifest() {
21
25
  if (!this._manifest)
@@ -32,6 +36,21 @@ export class DQLContext {
32
36
  this._lineage = buildGraphFromManifest(this.manifest);
33
37
  return this._lineage;
34
38
  }
39
+ /**
40
+ * Lazily-loaded registry of DataLex contracts for enforcing
41
+ * `datalex_contract` references on certified blocks. Tools call
42
+ * `registry.isLoaded()` to check whether a manifest was found before
43
+ * gating on resolution; that lets MCP work in projects that haven't
44
+ * adopted DataLex yet.
45
+ */
46
+ get datalexRegistry() {
47
+ if (!this._datalexRegistry) {
48
+ this._datalexRegistry = new DataLexContractRegistry({
49
+ manifestPath: this.datalexManifestPath,
50
+ });
51
+ }
52
+ return this._datalexRegistry;
53
+ }
35
54
  refresh() {
36
55
  const dbtManifestPath = resolveDbtManifestPath(this.projectRoot) ?? undefined;
37
56
  this._manifest = buildManifest({
@@ -59,6 +78,7 @@ export class DQLContext {
59
78
  this._semanticLayer = new SemanticLayer();
60
79
  }
61
80
  this._lineage = null;
81
+ this._datalexRegistry?.reload();
62
82
  }
63
83
  }
64
84
  function buildGraphFromManifest(manifest) {
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAWpE,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,SAAS,CAmE/E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAapE,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,SAAS,CAyG/E"}
package/dist/server.js CHANGED
@@ -7,24 +7,52 @@ import { listMetrics, listMetricsInput, listDimensions, listDimensionsInput } fr
7
7
  import { lineageImpact, lineageImpactInput } from './tools/lineage-impact.js';
8
8
  import { certify, certifyInput } from './tools/certify.js';
9
9
  import { suggestBlock, suggestBlockInput } from './tools/suggest-block.js';
10
+ import { queryViaMetadata, queryViaMetadataInput } from './tools/query-via-metadata.js';
11
+ import { listProposals, listProposalsInput } from './tools/list-proposals.js';
10
12
  import { kgSearch, kgSearchInput, feedbackRecord, feedbackRecordInput } from './tools/kg.js';
11
13
  export function createDQLMCPServer(options = {}) {
12
14
  const projectRoot = options.projectRoot ?? findProjectRoot(process.cwd());
13
15
  const ctx = new DQLContext({ projectRoot, dqlVersion: options.version });
14
16
  const server = new McpServer({ name: 'dql-mcp', version: options.version ?? '0.1.0' }, {
15
- instructions: 'DQL exposes certified, git-versioned analytics blocks. Every answer you build ' +
16
- 'should be grounded in a block returned by search_blocks / get_block. Use ' +
17
- 'query_via_block to execute never fabricate SQL. Use suggest_block when a ' +
18
- 'new question needs a new block; the governance gate returns which rules pass.',
17
+ instructions: 'DQL exposes certified, git-versioned analytics blocks under graduated trust:\n' +
18
+ ' Tier 1 Always try `query_via_block` first. It only serves blocks that are ' +
19
+ '`status = "certified"` AND have a resolved `datalex_contract`. The answer is ' +
20
+ 'safe to ship to dashboards.\n' +
21
+ ' Tier 2 — When no certified block matches, call `query_via_metadata` with the ' +
22
+ 'SQL you inferred from the manifest + dbt schema. The result is returned with ' +
23
+ '`uncertified: true` — surface that flag to the user verbatim. The proposal is ' +
24
+ 'auto-saved as a draft block under blocks/_drafts/ for human certification.\n' +
25
+ ' Tier 3 — If the question is unanswerable from the available data, refuse and ' +
26
+ 'tell the user why.\n' +
27
+ 'Other tools support the loop: `search_blocks` / `get_block` to discover Tier-1 ' +
28
+ 'matches, `list_proposals` to see the review queue, `suggest_block` to propose ' +
29
+ 'a new block source-of-truth, `certify` to evaluate governance rules, ' +
30
+ '`lineage_impact` to trace upstream/downstream, `list_metrics` / ' +
31
+ '`list_dimensions` for the semantic layer. Never fabricate SQL outside ' +
32
+ '`query_via_metadata` — it captures provenance the human needs to certify.',
19
33
  });
20
34
  server.registerTool('search_blocks', { description: 'Find certified DQL blocks by keyword, domain, or status.', inputSchema: searchBlocksInput }, async (args) => wrap(await searchBlocks(ctx, args)));
21
35
  server.registerTool('get_block', { description: 'Return full metadata, dependencies, and SQL for a block.', inputSchema: getBlockInput }, async (args) => wrap(await getBlock(ctx, args)));
22
- server.registerTool('query_via_block', { description: 'Execute a certified block against the local DQL runtime.', inputSchema: queryViaBlockInput }, async (args) => wrap(await queryViaBlock(ctx, args)));
36
+ server.registerTool('query_via_block', {
37
+ description: 'Tier-1 of graduated trust. Execute a certified block against the local DQL runtime. Refuses non-certified blocks AND certified blocks whose datalex_contract reference is unresolved. Always try this first; fall back to query_via_metadata only when this returns "no block named".',
38
+ inputSchema: queryViaBlockInput,
39
+ }, async (args) => wrap(await queryViaBlock(ctx, args)));
40
+ server.registerTool('query_via_metadata', {
41
+ description: 'Tier-2 of graduated trust. Use ONLY when query_via_block has no matching certified block. Provide the SQL you inferred from the manifest + dbt schema; the runtime executes it and returns the result with `uncertified: true`. The proposal is auto-saved as a draft block under blocks/_drafts/. Surface the `uncertified` flag verbatim and tell the user about the `dql certify --from-draft` command if they want the answer certified for next time.',
42
+ inputSchema: queryViaMetadataInput,
43
+ }, async (args) => wrap(await queryViaMetadata(ctx, args)));
44
+ server.registerTool('list_proposals', {
45
+ description: 'List Tier-2 draft proposals from blocks/_drafts/ ordered by askedTimes DESC. Filter with askedAtLeastTimes / since. Use this to surface "questions that get asked repeatedly are good certify candidates" — the prioritization signal for the human review queue.',
46
+ inputSchema: listProposalsInput,
47
+ }, async (args) => wrap(listProposals(ctx, args)));
23
48
  server.registerTool('list_metrics', { description: 'List semantic-layer metrics, optionally filtered by domain.', inputSchema: listMetricsInput }, async (args) => wrap(await listMetrics(ctx, args)));
24
49
  server.registerTool('list_dimensions', { description: 'List semantic-layer dimensions, optionally filtered by domain.', inputSchema: listDimensionsInput }, async (args) => wrap(await listDimensions(ctx, args)));
25
50
  server.registerTool('lineage_impact', { description: 'Return upstream/downstream lineage for a block, metric, or model.', inputSchema: lineageImpactInput }, async (args) => wrap(await lineageImpact(ctx, args)));
26
51
  server.registerTool('certify', { description: 'Run governance rules against a block and report pass/fail.', inputSchema: certifyInput }, async (args) => wrap(await certify(ctx, args)));
27
- server.registerTool('suggest_block', { description: 'Write a proposed block to blocks/_drafts/ and return the governance gate result.', inputSchema: suggestBlockInput }, async (args) => wrap(await suggestBlock(ctx, args)));
52
+ server.registerTool('suggest_block', {
53
+ description: 'Write a curated proposed block to blocks/_drafts/ with a hand-shaped name + structure, plus the governance gate result. Use when proposing a SHARED building block on top of multiple Tier-2 proposals. For one-shot ad-hoc Tier-2 captures, use `query_via_metadata` instead — it auto-saves the draft.',
54
+ inputSchema: suggestBlockInput,
55
+ }, async (args) => wrap(await suggestBlock(ctx, args)));
28
56
  server.registerTool('kg_search', { description: 'Search the agent knowledge graph (FTS5) over blocks, metrics, dimensions, dashboards, apps.', inputSchema: kgSearchInput }, async (args) => wrap(kgSearch(ctx, args)));
29
57
  server.registerTool('feedback_record', { description: 'Record thumbs-up/down feedback on an answer; feeds self-learning + promotion suggestions.', inputSchema: feedbackRecordInput }, async (args) => wrap(feedbackRecord(ctx, args)));
30
58
  return server;
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { DQLContext } from '../../context.js';
2
+ export declare function makeManifestBlock(overrides?: Record<string, unknown>): Record<string, unknown>;
3
+ export declare function makeCtx(blocks?: Record<string, unknown>, extra?: Partial<DQLContext>): DQLContext;
4
+ //# sourceMappingURL=_helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_helpers.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAWlE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC7B;AAeD,wBAAgB,OAAO,CAAC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,KAAK,GAAE,OAAO,CAAC,UAAU,CAAM,GAAG,UAAU,CAOzG"}
@@ -0,0 +1,34 @@
1
+ export function makeManifestBlock(overrides = {}) {
2
+ return {
3
+ name: 'My Block',
4
+ status: 'certified',
5
+ type: 'custom',
6
+ domain: 'finance',
7
+ filePath: 'blocks/my-block.dql',
8
+ description: 'Stub block used by tests.',
9
+ owner: 'tests@example.com',
10
+ tags: [],
11
+ ...overrides,
12
+ };
13
+ }
14
+ /**
15
+ * Default registry stub: `isLoaded()` returns false so query-via-block's
16
+ * datalex_contract check is skipped, matching the "DataLex not yet adopted"
17
+ * path. Specific tests pass a real registry via `extra.datalexRegistry`.
18
+ */
19
+ const skipRegistry = {
20
+ isLoaded: () => false,
21
+ resolve: () => ({ ok: false, reason: 'not_found', message: '', requestedRef: '' }),
22
+ list: () => [],
23
+ reload: () => undefined,
24
+ loadDiagnostics: () => [],
25
+ };
26
+ export function makeCtx(blocks = {}, extra = {}) {
27
+ return {
28
+ projectRoot: '/test/project',
29
+ manifest: { blocks },
30
+ datalexRegistry: skipRegistry,
31
+ ...extra,
32
+ };
33
+ }
34
+ //# sourceMappingURL=_helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_helpers.js","sourceRoot":"","sources":["../../../src/tools/__tests__/_helpers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,YAAqC,EAAE;IACvE,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,qBAAqB;QAC/B,WAAW,EAAE,2BAA2B;QACxC,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,EAAE;QACR,GAAG,SAAS;KACc,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,YAAY,GAAG;IACnB,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK;IACrB,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAClF,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS;IACvB,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE;CAC1B,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,SAAkC,EAAE,EAAE,QAA6B,EAAE;IAC3F,OAAO;QACL,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,EAAE,MAAM,EAAE;QACpB,eAAe,EAAE,YAAY;QAC7B,GAAG,KAAK;KACgB,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { z } from 'zod';
2
+ import type { DQLContext } from '../context.js';
3
+ export declare const listProposalsInput: {
4
+ askedAtLeastTimes: z.ZodOptional<z.ZodNumber>;
5
+ since: z.ZodOptional<z.ZodString>;
6
+ };
7
+ export interface ProposalSummary {
8
+ draftPath: string;
9
+ slug: string;
10
+ question: string;
11
+ askedTimes: number;
12
+ firstAsked: string;
13
+ lastAsked: string;
14
+ proposedContractId: string;
15
+ proposedDomain: string;
16
+ proposedEntity: string;
17
+ upstreamRefs: string[];
18
+ certifyHint: string;
19
+ }
20
+ /**
21
+ * The OSS-side review queue for the Tier-2 promotion loop. Reads
22
+ * `blocks/_drafts/*.dql` from the project, parses the `_proposed { ... }`
23
+ * provenance block out of each, and returns a list ranked by `askedTimes`
24
+ * descending — questions that get asked repeatedly are the strongest
25
+ * candidates for certification.
26
+ *
27
+ * Multi-user team queues (RBAC, assignments, deadlines, audit logs) are
28
+ * commercial-overlay features. This OSS tool reads files from disk and
29
+ * commits to git when humans certify them. That's the shared store.
30
+ */
31
+ export declare function listProposals(ctx: DQLContext, args?: {
32
+ askedAtLeastTimes?: number;
33
+ since?: string;
34
+ }): {
35
+ proposals: ProposalSummary[];
36
+ };
37
+ //# sourceMappingURL=list-proposals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-proposals.d.ts","sourceRoot":"","sources":["../../src/tools/list-proposals.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;CAa9B,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,IAAI,GAAE;IAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD;IAAE,SAAS,EAAE,eAAe,EAAE,CAAA;CAAE,CAwBlC"}
@@ -0,0 +1,101 @@
1
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { z } from 'zod';
4
+ export const listProposalsInput = {
5
+ askedAtLeastTimes: z
6
+ .number()
7
+ .int()
8
+ .min(1)
9
+ .optional()
10
+ .describe('Filter to drafts asked at least N times (defaults to 1).'),
11
+ since: z
12
+ .string()
13
+ .optional()
14
+ .describe('ISO 8601 timestamp; only return drafts whose last_asked is on or after this. Useful for "what got asked this week?".'),
15
+ };
16
+ /**
17
+ * The OSS-side review queue for the Tier-2 promotion loop. Reads
18
+ * `blocks/_drafts/*.dql` from the project, parses the `_proposed { ... }`
19
+ * provenance block out of each, and returns a list ranked by `askedTimes`
20
+ * descending — questions that get asked repeatedly are the strongest
21
+ * candidates for certification.
22
+ *
23
+ * Multi-user team queues (RBAC, assignments, deadlines, audit logs) are
24
+ * commercial-overlay features. This OSS tool reads files from disk and
25
+ * commits to git when humans certify them. That's the shared store.
26
+ */
27
+ export function listProposals(ctx, args = {}) {
28
+ const draftDir = join(ctx.projectRoot, 'blocks', '_drafts');
29
+ if (!existsSync(draftDir))
30
+ return { proposals: [] };
31
+ const minTimes = args.askedAtLeastTimes ?? 1;
32
+ const sinceMs = args.since ? Date.parse(args.since) : null;
33
+ const proposals = [];
34
+ for (const entry of readdirSync(draftDir)) {
35
+ if (!entry.endsWith('.dql'))
36
+ continue;
37
+ const path = join(draftDir, entry);
38
+ const summary = parseProposal(readFileSync(path, 'utf-8'), entry, ctx.projectRoot);
39
+ if (!summary)
40
+ continue;
41
+ if (summary.askedTimes < minTimes)
42
+ continue;
43
+ if (sinceMs !== null && Date.parse(summary.lastAsked) < sinceMs)
44
+ continue;
45
+ proposals.push(summary);
46
+ }
47
+ proposals.sort((a, b) => {
48
+ if (b.askedTimes !== a.askedTimes)
49
+ return b.askedTimes - a.askedTimes;
50
+ return Date.parse(b.lastAsked) - Date.parse(a.lastAsked);
51
+ });
52
+ return { proposals };
53
+ }
54
+ function parseProposal(content, filename, projectRoot) {
55
+ const slug = filename.replace(/\.dql$/, '');
56
+ const question = pickStringField(content, 'description') ?? slug;
57
+ const askedTimes = pickIntField(content, 'asked_times', 1);
58
+ const firstAsked = pickStringField(content, 'first_asked') ?? '';
59
+ const lastAsked = pickStringField(content, 'last_asked') ?? '';
60
+ const proposedContractId = pickStringField(content, 'proposed_contract_id') ?? '';
61
+ const proposedDomain = pickStringField(content, 'proposed_domain') ?? '';
62
+ const proposedEntity = pickStringField(content, 'proposed_entity') ?? '';
63
+ const upstreamRefs = pickArrayField(content, 'upstream_refs');
64
+ const draftPath = relativeTo(projectRoot, `blocks/_drafts/${filename}`);
65
+ const certifyHint = `dql certify --from-draft ${draftPath} --domain ${proposedDomain || '<domain>'} --contract ${proposedContractId || '<id>'}@1 --owner <you@example.com>`;
66
+ return {
67
+ draftPath,
68
+ slug,
69
+ question,
70
+ askedTimes,
71
+ firstAsked,
72
+ lastAsked,
73
+ proposedContractId,
74
+ proposedDomain,
75
+ proposedEntity,
76
+ upstreamRefs,
77
+ certifyHint,
78
+ };
79
+ }
80
+ function pickStringField(content, key) {
81
+ const m = content.match(new RegExp(`${key}\\s*=\\s*"([^"]*)"`)) ||
82
+ content.match(new RegExp(`${key}\\s*=\\s*"""([\\s\\S]*?)"""`));
83
+ return m?.[1]?.trim();
84
+ }
85
+ function pickIntField(content, key, defaultValue) {
86
+ const m = content.match(new RegExp(`${key}\\s*=\\s*(\\d+)`));
87
+ return m ? Number.parseInt(m[1], 10) : defaultValue;
88
+ }
89
+ function pickArrayField(content, key) {
90
+ const m = content.match(new RegExp(`${key}\\s*=\\s*\\[([^\\]]*)\\]`));
91
+ if (!m)
92
+ return [];
93
+ return m[1]
94
+ .split(',')
95
+ .map((s) => s.trim().replace(/^"|"$/g, ''))
96
+ .filter((s) => s.length > 0);
97
+ }
98
+ function relativeTo(root, relPath) {
99
+ return relPath.startsWith('/') ? relPath : relPath;
100
+ }
101
+ //# sourceMappingURL=list-proposals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-proposals.js","sourceRoot":"","sources":["../../src/tools/list-proposals.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"query-via-block.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;CAS9B,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;cA+C9B,MAAM;eAAS,MAAM;;;;GAiBlD"}
1
+ {"version":3,"file":"query-via-block.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;CAS9B,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;cA+D9B,MAAM;eAAS,MAAM;;;;GAiBlD"}
@@ -23,6 +23,21 @@ export async function queryViaBlock(ctx, args) {
23
23
  error: `Block "${args.name}" is "${block.status ?? 'draft'}" — only certified blocks can be executed via MCP.`,
24
24
  };
25
25
  }
26
+ // v1.6 — DataLex contract enforcement (the wedge).
27
+ // When a certified block declares datalex_contract, refuse the call if
28
+ // the reference doesn't resolve in the project's loaded DataLex
29
+ // manifest. We do NOT fail when no manifest is loaded — projects that
30
+ // haven't adopted DataLex still work; the analyzer separately surfaces a
31
+ // warning at compile time so the user is aware.
32
+ const datalexContract = block.datalexContract;
33
+ if (datalexContract && ctx.datalexRegistry.isLoaded()) {
34
+ const resolution = ctx.datalexRegistry.resolve(datalexContract);
35
+ if (!resolution.ok) {
36
+ return {
37
+ error: `Block "${args.name}" references DataLex contract "${datalexContract}" which ${resolution.reason === 'not_found' ? 'is not in the loaded DataLex manifest' : resolution.reason === 'version_mismatch' ? `pins a version that does not exist (available: ${(resolution.availableVersions ?? []).join(', ')})` : `is malformed (${resolution.message})`}. Refusing to serve until the contract resolves.`,
38
+ };
39
+ }
40
+ }
26
41
  const base = args.serverUrl ?? process.env.DQL_RUNTIME_URL ?? 'http://127.0.0.1:3474';
27
42
  const url = `${base.replace(/\/$/, '')}/api/notebook/execute`;
28
43
  let source;
@@ -1 +1 @@
1
- {"version":3,"file":"query-via-block.js","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query-via-block.js","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import { z } from 'zod';
2
+ import type { DQLContext } from '../context.js';
3
+ export declare const queryViaMetadataInput: {
4
+ question: z.ZodString;
5
+ proposedSql: z.ZodString;
6
+ upstreamRefs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
7
+ proposedDomain: z.ZodOptional<z.ZodString>;
8
+ proposedEntity: z.ZodOptional<z.ZodString>;
9
+ saveDraft: z.ZodOptional<z.ZodBoolean>;
10
+ dryRun: z.ZodOptional<z.ZodBoolean>;
11
+ limit: z.ZodOptional<z.ZodNumber>;
12
+ serverUrl: z.ZodOptional<z.ZodString>;
13
+ };
14
+ /**
15
+ * Tier-2 of the graduated-trust loop. Use ONLY after `query_via_block` has
16
+ * confirmed there's no certified block for the question.
17
+ *
18
+ * - Executes the proposed SQL against the local runtime (unless dryRun).
19
+ * - Returns the result with `uncertified: true` so the agent surfaces the
20
+ * trust label to the human.
21
+ * - Optionally captures the proposal as a draft block at
22
+ * `blocks/_drafts/<slug>.dql`. Same question = same slug; askedTimes
23
+ * counter increments on dedupe.
24
+ *
25
+ * The agent contract: surface `uncertified: true` verbatim, and tell the
26
+ * user about the draft block path + the `dql certify --from-draft` command
27
+ * if they want the answer certified for next time.
28
+ */
29
+ export declare function queryViaMetadata(ctx: DQLContext, args: {
30
+ question: string;
31
+ proposedSql: string;
32
+ upstreamRefs?: string[];
33
+ proposedDomain?: string;
34
+ proposedEntity?: string;
35
+ saveDraft?: boolean;
36
+ dryRun?: boolean;
37
+ limit?: number;
38
+ serverUrl?: string;
39
+ }): Promise<{
40
+ uncertified: boolean;
41
+ reason: string;
42
+ proposedSql: string;
43
+ draftBlock: {
44
+ path: string;
45
+ askedTimes: number;
46
+ proposedContractId: string;
47
+ } | undefined;
48
+ promote: string | undefined;
49
+ error?: undefined;
50
+ question?: undefined;
51
+ rowCount?: undefined;
52
+ durationMs?: undefined;
53
+ columns?: undefined;
54
+ rows?: undefined;
55
+ } | {
56
+ uncertified: boolean;
57
+ error: string;
58
+ draftBlock: {
59
+ path: string;
60
+ askedTimes: number;
61
+ proposedContractId: string;
62
+ } | undefined;
63
+ reason?: undefined;
64
+ proposedSql?: undefined;
65
+ promote?: undefined;
66
+ question?: undefined;
67
+ rowCount?: undefined;
68
+ durationMs?: undefined;
69
+ columns?: undefined;
70
+ rows?: undefined;
71
+ } | {
72
+ uncertified: boolean;
73
+ reason: string;
74
+ question: string;
75
+ rowCount: number;
76
+ durationMs: number | null;
77
+ columns: {
78
+ name: string;
79
+ type?: string;
80
+ }[];
81
+ rows: unknown[];
82
+ draftBlock: {
83
+ path: string;
84
+ askedTimes: number;
85
+ proposedContractId: string;
86
+ } | undefined;
87
+ promote: string | undefined;
88
+ proposedSql?: undefined;
89
+ error?: undefined;
90
+ }>;
91
+ /**
92
+ * Derive a deterministic snake_case slug from a free-form question. Same
93
+ * question -> same slug, so re-asking the question increments `asked_times`
94
+ * on the existing draft instead of creating a new file.
95
+ *
96
+ * v1: lowercase, strip punctuation, drop stopwords + common quantifiers
97
+ * (e.g. "how many"), join with `_`. Truncated to 60 chars to keep file
98
+ * paths sensible. Not perfect across paraphrases — that's a v2 problem.
99
+ */
100
+ export declare function deriveSlug(question: string): string;
101
+ //# sourceMappingURL=query-via-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-via-metadata.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-metadata.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,qBAAqB;;;;;;;;;;CAsDjC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;cAKuB,MAAM;oBAAc,MAAM;4BAAsB,MAAM;;;;;;;;;;;;;cAAtD,MAAM;oBAAc,MAAM;4BAAsB,MAAM;;;;;;;;;;;;;;;;;cA4DlD,MAAM;eAAS,MAAM;;;;cA5DzB,MAAM;oBAAc,MAAM;4BAAsB,MAAM;;;;;GAoF/E;AAYD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQnD"}
@@ -0,0 +1,246 @@
1
+ import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { z } from 'zod';
4
+ export const queryViaMetadataInput = {
5
+ question: z
6
+ .string()
7
+ .min(1)
8
+ .describe('The user question being answered, verbatim. Used for the draft block name and description.'),
9
+ proposedSql: z
10
+ .string()
11
+ .min(1)
12
+ .describe('SQL the agent inferred from the available manifest + dbt schema. Will be executed through the local DQL runtime against the certified data plane.'),
13
+ upstreamRefs: z
14
+ .array(z.string())
15
+ .optional()
16
+ .describe('Tables / blocks the agent thinks are involved.'),
17
+ proposedDomain: z
18
+ .string()
19
+ .optional()
20
+ .describe('Best guess at the DataLex domain that owns this question (e.g. "customer", "finance"). Used to suggest a contract id.'),
21
+ proposedEntity: z
22
+ .string()
23
+ .optional()
24
+ .describe('Best guess at the entity (PascalCase, e.g. "Customer"). Used together with proposedDomain to suggest a contract id.'),
25
+ saveDraft: z
26
+ .boolean()
27
+ .optional()
28
+ .describe('Persist a draft .dql file under blocks/_drafts/ for later human review and certification. Default true.'),
29
+ dryRun: z
30
+ .boolean()
31
+ .optional()
32
+ .describe('If true, return the proposed SQL + lineage without executing. Default false (execute).'),
33
+ limit: z
34
+ .number()
35
+ .int()
36
+ .min(1)
37
+ .max(10000)
38
+ .optional()
39
+ .describe('Max rows to return on execution.'),
40
+ serverUrl: z
41
+ .string()
42
+ .optional()
43
+ .describe('Base URL of the local DQL runtime (default http://127.0.0.1:3474). Start it with `dql serve`.'),
44
+ };
45
+ /**
46
+ * Tier-2 of the graduated-trust loop. Use ONLY after `query_via_block` has
47
+ * confirmed there's no certified block for the question.
48
+ *
49
+ * - Executes the proposed SQL against the local runtime (unless dryRun).
50
+ * - Returns the result with `uncertified: true` so the agent surfaces the
51
+ * trust label to the human.
52
+ * - Optionally captures the proposal as a draft block at
53
+ * `blocks/_drafts/<slug>.dql`. Same question = same slug; askedTimes
54
+ * counter increments on dedupe.
55
+ *
56
+ * The agent contract: surface `uncertified: true` verbatim, and tell the
57
+ * user about the draft block path + the `dql certify --from-draft` command
58
+ * if they want the answer certified for next time.
59
+ */
60
+ export async function queryViaMetadata(ctx, args) {
61
+ const slug = deriveSlug(args.question);
62
+ const proposedContractId = suggestContractId(slug, args.proposedDomain, args.proposedEntity);
63
+ let draftBlock;
64
+ if (args.saveDraft !== false) {
65
+ draftBlock = upsertDraft(ctx.projectRoot, {
66
+ slug,
67
+ question: args.question,
68
+ proposedSql: args.proposedSql,
69
+ proposedContractId,
70
+ proposedDomain: args.proposedDomain,
71
+ proposedEntity: args.proposedEntity,
72
+ upstreamRefs: args.upstreamRefs ?? [],
73
+ });
74
+ }
75
+ if (args.dryRun) {
76
+ return {
77
+ uncertified: true,
78
+ reason: 'dryRun=true; SQL not executed. Returned proposal only.',
79
+ proposedSql: args.proposedSql,
80
+ draftBlock,
81
+ promote: draftBlock
82
+ ? `if you want this question certified, run: dql certify --from-draft ${draftBlock.path}`
83
+ : undefined,
84
+ };
85
+ }
86
+ const base = args.serverUrl ?? process.env.DQL_RUNTIME_URL ?? 'http://127.0.0.1:3474';
87
+ const url = `${base.replace(/\/$/, '')}/api/notebook/execute`;
88
+ let response;
89
+ try {
90
+ response = await fetch(url, {
91
+ method: 'POST',
92
+ headers: { 'Content-Type': 'application/json' },
93
+ body: JSON.stringify({
94
+ cell: {
95
+ id: `mcp-tier2-${slug}`,
96
+ type: 'dql',
97
+ source: wrapSqlAsDqlCell(args.proposedSql),
98
+ title: args.question,
99
+ },
100
+ }),
101
+ });
102
+ }
103
+ catch (err) {
104
+ return {
105
+ uncertified: true,
106
+ error: `Could not reach DQL runtime at ${base}. Start it with \`dql serve\` in ${ctx.projectRoot}. (${err instanceof Error ? err.message : String(err)})`,
107
+ draftBlock,
108
+ };
109
+ }
110
+ if (!response.ok) {
111
+ return {
112
+ uncertified: true,
113
+ error: `Runtime returned ${response.status}: ${await response.text()}`,
114
+ draftBlock,
115
+ };
116
+ }
117
+ const payload = (await response.json());
118
+ if (payload.error) {
119
+ return { uncertified: true, error: payload.error, draftBlock };
120
+ }
121
+ const rows = payload.result?.rows ?? [];
122
+ return {
123
+ uncertified: true,
124
+ reason: 'no certified block matched the question; result derived from manifest + dbt schema',
125
+ question: args.question,
126
+ rowCount: rows.length,
127
+ durationMs: payload.result?.executionTime ?? null,
128
+ columns: payload.result?.columns ?? [],
129
+ rows: args.limit ? rows.slice(0, args.limit) : rows,
130
+ draftBlock,
131
+ promote: draftBlock
132
+ ? `if you want this question certified, run: dql certify --from-draft ${draftBlock.path}`
133
+ : undefined,
134
+ };
135
+ }
136
+ // -- helpers ---------------------------------------------------------------
137
+ const STOPWORDS = new Set([
138
+ 'a', 'an', 'and', 'are', 'as', 'at', 'be', 'by', 'do', 'for', 'from',
139
+ 'has', 'have', 'how', 'i', 'in', 'is', 'it', 'me', 'much', 'my', 'of',
140
+ 'on', 'or', 'our', 'so', 'that', 'the', 'their', 'then', 'there', 'this',
141
+ 'to', 'us', 'was', 'we', 'were', 'what', 'when', 'where', 'which', 'who',
142
+ 'why', 'will', 'with', 'you', 'your',
143
+ ]);
144
+ /**
145
+ * Derive a deterministic snake_case slug from a free-form question. Same
146
+ * question -> same slug, so re-asking the question increments `asked_times`
147
+ * on the existing draft instead of creating a new file.
148
+ *
149
+ * v1: lowercase, strip punctuation, drop stopwords + common quantifiers
150
+ * (e.g. "how many"), join with `_`. Truncated to 60 chars to keep file
151
+ * paths sensible. Not perfect across paraphrases — that's a v2 problem.
152
+ */
153
+ export function deriveSlug(question) {
154
+ const tokens = question
155
+ .toLowerCase()
156
+ .replace(/[^a-z0-9\s]/g, ' ')
157
+ .split(/\s+/)
158
+ .filter((t) => t.length > 0 && !STOPWORDS.has(t));
159
+ const slug = tokens.join('_').slice(0, 60).replace(/_+$/, '');
160
+ return slug || 'untitled_proposal';
161
+ }
162
+ function suggestContractId(slug, domain, entity) {
163
+ const d = (domain || 'misc').toLowerCase();
164
+ const e = entity && /^[A-Z]/.test(entity) ? entity : 'Unknown';
165
+ return `${d}.${e}.${slug}`;
166
+ }
167
+ function wrapSqlAsDqlCell(sql) {
168
+ // Tier-2 cells are raw SQL. The runtime accepts SQL directly; no DQL
169
+ // block wrapper is required for execution.
170
+ return sql;
171
+ }
172
+ function upsertDraft(projectRoot, rec) {
173
+ const draftDir = join(projectRoot, 'blocks', '_drafts');
174
+ const filePath = join(draftDir, `${rec.slug}.dql`);
175
+ if (existsSync(filePath)) {
176
+ const existing = readFileSync(filePath, 'utf-8');
177
+ const m = existing.match(/asked_times\s*=\s*(\d+)/);
178
+ const prev = m ? Number.parseInt(m[1], 10) : 1;
179
+ const next = Number.isFinite(prev) ? prev + 1 : 2;
180
+ const updated = m
181
+ ? existing.replace(/asked_times\s*=\s*\d+/, `asked_times = ${next}`)
182
+ : existing.replace(/_proposed\s*\{/, `_proposed {\n asked_times = ${next}`);
183
+ const stamped = stampLastAsked(updated);
184
+ writeFileSync(filePath, stamped);
185
+ return {
186
+ path: relativeToProject(projectRoot, filePath),
187
+ askedTimes: next,
188
+ proposedContractId: rec.proposedContractId,
189
+ };
190
+ }
191
+ mkdirSync(dirname(filePath), { recursive: true });
192
+ writeFileSync(filePath, renderDraft(rec));
193
+ return {
194
+ path: relativeToProject(projectRoot, filePath),
195
+ askedTimes: 1,
196
+ proposedContractId: rec.proposedContractId,
197
+ };
198
+ }
199
+ function relativeToProject(root, abs) {
200
+ const rootSlash = root.endsWith('/') ? root : root + '/';
201
+ return abs.startsWith(rootSlash) ? abs.slice(rootSlash.length) : abs;
202
+ }
203
+ function renderDraft(rec) {
204
+ const now = new Date().toISOString();
205
+ const upstream = rec.upstreamRefs.length > 0
206
+ ? `\n upstream_refs = [${rec.upstreamRefs.map((u) => `"${u}"`).join(', ')}]`
207
+ : '';
208
+ // Single quoted SQL inside triple-double-quotes; avoid breaking on `"""` in user SQL.
209
+ const safeSql = rec.proposedSql.replace(/"""/g, '\\"\\"\\"');
210
+ return `block "${rec.slug}" {
211
+ domain = "${rec.proposedDomain ?? 'misc'}"
212
+ type = "custom"
213
+ status = "draft"
214
+ description = """${rec.question}"""
215
+
216
+ # Tier-2 proposal — auto-captured from query_via_metadata. Reviewer
217
+ # fills in datalex_contract + owner, then runs:
218
+ # dql certify --from-draft blocks/_drafts/${rec.slug}.dql \\
219
+ # --domain ${rec.proposedDomain ?? 'misc'} \\
220
+ # --contract ${rec.proposedContractId}@1 \\
221
+ # --owner you@example.com
222
+ datalex_contract = ""
223
+
224
+ _proposed {
225
+ asked_times = 1
226
+ first_asked = "${now}"
227
+ last_asked = "${now}"
228
+ proposed_contract_id = "${rec.proposedContractId}"
229
+ proposed_domain = "${rec.proposedDomain ?? ''}"
230
+ proposed_entity = "${rec.proposedEntity ?? ''}"${upstream}
231
+ }
232
+
233
+ query = """
234
+ ${safeSql.split('\n').join('\n ')}
235
+ """
236
+ }
237
+ `;
238
+ }
239
+ function stampLastAsked(content) {
240
+ const now = new Date().toISOString();
241
+ if (/last_asked\s*=\s*"[^"]*"/.test(content)) {
242
+ return content.replace(/last_asked\s*=\s*"[^"]*"/, `last_asked = "${now}"`);
243
+ }
244
+ return content;
245
+ }
246
+ //# sourceMappingURL=query-via-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-via-metadata.js","sourceRoot":"","sources":["../../src/tools/query-via-metadata.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckcodeailabs/dql-mcp",
3
- "version": "1.5.3",
3
+ "version": "1.6.0",
4
4
  "description": "DQL MCP server: expose certified blocks, semantic layer, lineage, and governance to LLM agents via the Model Context Protocol",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -24,12 +24,12 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@duckcodeailabs/dql-agent": "^1.5.3",
28
- "@duckcodeailabs/dql-core": "^1.5.3",
29
- "@duckcodeailabs/dql-governance": "^1.5.3",
30
- "@duckcodeailabs/dql-project": "^1.5.3",
31
27
  "@modelcontextprotocol/sdk": "^1.0.4",
32
- "zod": "^3.25.0"
28
+ "zod": "^3.25.0",
29
+ "@duckcodeailabs/dql-agent": "1.6.0",
30
+ "@duckcodeailabs/dql-project": "1.6.0",
31
+ "@duckcodeailabs/dql-governance": "1.6.0",
32
+ "@duckcodeailabs/dql-core": "1.6.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^20.0.0",