@structured-vibe-coding/core 0.21.0 → 0.23.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.
@@ -6,8 +6,13 @@ import {
6
6
  shouldAutoSkip
7
7
  } from "./chunk-TNWFMRIA.js";
8
8
  import {
9
- SddError
10
- } from "./chunk-MHODNFIL.js";
9
+ SddError,
10
+ callMcpSourceTool,
11
+ mcpTimeoutMs
12
+ } from "./chunk-OY47H6R5.js";
13
+ import {
14
+ loadMcpConfig
15
+ } from "./chunk-4BRO7BOJ.js";
11
16
  import {
12
17
  activePointerPath,
13
18
  changesPathRel,
@@ -196,7 +201,9 @@ var SearchConfigSchema = z.object({
196
201
  k: z.number().int().min(1).max(100).default(20),
197
202
  embeddings: z.boolean().default(false),
198
203
  budgets: BudgetSchema.default({ default: 12e3 }),
199
- exclude: z.array(z.string().min(1)).default([])
204
+ exclude: z.array(z.string().min(1)).default([]),
205
+ mcp_source: z.string().min(1).optional(),
206
+ mcp_tool: z.string().min(1).optional()
200
207
  });
201
208
  function budgetForStage(config, stage) {
202
209
  if (!stage) return config.budgets.default;
@@ -221,22 +228,13 @@ async function loadSearchConfig(projectRoot) {
221
228
 
222
229
  // src/search/pack.ts
223
230
  var EN_DASH = "\u2013";
224
- function searchPreamble(query, scope, budget, hybrid = false) {
225
- if (hybrid) {
226
- return `# Search
227
- Query: ${query}
228
- Scope: ${scope}
229
- Provider: builtin
230
- Mode: hybrid
231
- Budget: ${budget}
232
-
233
- `;
234
- }
231
+ function searchPreamble(query, scope, budget, hybrid = false, provider = "builtin") {
232
+ const mode = hybrid ? "Mode: hybrid\n" : "";
235
233
  return `# Search
236
234
  Query: ${query}
237
235
  Scope: ${scope}
238
- Provider: builtin
239
- Budget: ${budget}
236
+ Provider: ${provider}
237
+ ${mode}Budget: ${budget}
240
238
 
241
239
  `;
242
240
  }
@@ -2331,6 +2329,173 @@ async function searchProject(projectRoot, query, options, runtime) {
2331
2329
  };
2332
2330
  }
2333
2331
 
2332
+ // src/search/mcp-provider.ts
2333
+ var McpSearchError = class extends Error {
2334
+ constructor() {
2335
+ super("Search provider is unavailable.");
2336
+ this.name = "McpSearchError";
2337
+ }
2338
+ };
2339
+ function emptyStats(considered = 0, reindexed = 0) {
2340
+ return {
2341
+ provider: "mcp",
2342
+ files: 0,
2343
+ chunks: 0,
2344
+ lastIndexFilesConsidered: considered,
2345
+ lastIndexFilesReindexed: reindexed,
2346
+ lastIndexChunksReindexed: 0,
2347
+ lastIndexChunksEmbedded: 0,
2348
+ indexedCommit: null
2349
+ };
2350
+ }
2351
+ function isSafeRelativePath(path) {
2352
+ if (!path || path.startsWith("/") || path.startsWith("\\")) return false;
2353
+ if (path.length >= 2 && path.charCodeAt(1) === 58) {
2354
+ const c = path.charCodeAt(0);
2355
+ if (c >= 65 && c <= 90 || c >= 97 && c <= 122) return false;
2356
+ }
2357
+ const parts = path.replaceAll("\\", "/").split("/");
2358
+ for (const part of parts) {
2359
+ if (part.length === 0 || part === "." || part === "..") return false;
2360
+ }
2361
+ return true;
2362
+ }
2363
+ function withTimeout(promise, ms) {
2364
+ return new Promise((resolve, reject) => {
2365
+ const timer = setTimeout(() => reject(new McpSearchError()), ms);
2366
+ promise.then(
2367
+ (value) => {
2368
+ clearTimeout(timer);
2369
+ resolve(value);
2370
+ },
2371
+ () => {
2372
+ clearTimeout(timer);
2373
+ reject(new McpSearchError());
2374
+ }
2375
+ );
2376
+ });
2377
+ }
2378
+ function allowedPaths(paths, exclude) {
2379
+ const kept = [];
2380
+ for (const raw of paths) {
2381
+ const path = raw.replaceAll("\\", "/");
2382
+ if (!isSafeRelativePath(path) || exclude(path)) continue;
2383
+ kept.push(path);
2384
+ }
2385
+ return kept;
2386
+ }
2387
+ function positive(value) {
2388
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1) return void 0;
2389
+ return value;
2390
+ }
2391
+ function firstLine(body) {
2392
+ const nl = body.indexOf("\n");
2393
+ return nl === -1 ? body : body.slice(0, nl);
2394
+ }
2395
+ function asHit(value, scope, exclude) {
2396
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
2397
+ const rec = value;
2398
+ if (typeof rec.path !== "string") return void 0;
2399
+ const path = rec.path.replaceAll("\\", "/");
2400
+ if (!isSafeRelativePath(path) || exclude(path)) return void 0;
2401
+ const startLine2 = positive(rec.startLine);
2402
+ const endLine2 = positive(rec.endLine);
2403
+ if (startLine2 === void 0 || endLine2 === void 0 || endLine2 < startLine2) return void 0;
2404
+ if (typeof rec.symbol !== "string") return void 0;
2405
+ const symbol = rec.symbol.trim();
2406
+ if (!symbol || typeof rec.body !== "string") return void 0;
2407
+ const signature = typeof rec.signature === "string" ? rec.signature : firstLine(rec.body);
2408
+ const language = typeof rec.language === "string" ? rec.language : "";
2409
+ const score = typeof rec.score === "number" && Number.isFinite(rec.score) ? rec.score : 0;
2410
+ return { scope, path, startLine: startLine2, endLine: endLine2, symbol, score, signature, body: rec.body, language };
2411
+ }
2412
+ function parseHits(text, scope, exclude) {
2413
+ let parsed;
2414
+ try {
2415
+ parsed = JSON.parse(text);
2416
+ } catch {
2417
+ throw new McpSearchError();
2418
+ }
2419
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new McpSearchError();
2420
+ const hits = parsed.hits;
2421
+ if (!Array.isArray(hits)) throw new McpSearchError();
2422
+ const out = [];
2423
+ for (const hit of hits) {
2424
+ const row = asHit(hit, scope, exclude);
2425
+ if (row) out.push(row);
2426
+ }
2427
+ return out;
2428
+ }
2429
+ async function connect(input) {
2430
+ const exclude = await loadExcluder(input.projectRoot, input.search.exclude);
2431
+ let sources = [];
2432
+ try {
2433
+ const cfg = await loadMcpConfig(input.projectRoot);
2434
+ sources = cfg.sources.filter((source2) => source2.enabled);
2435
+ } catch {
2436
+ throw new McpSearchError();
2437
+ }
2438
+ const named = input.search.mcp_source;
2439
+ const source = named ? sources.find((item) => item.id === named) : sources.length === 1 ? sources[0] : void 0;
2440
+ if (!source) throw new McpSearchError();
2441
+ const tool = input.search.mcp_tool || source.invoke?.tool;
2442
+ if (!tool) throw new McpSearchError();
2443
+ if (source.tools?.length && !source.tools.includes(tool)) throw new McpSearchError();
2444
+ const call = input.call ?? (async (req) => {
2445
+ const result = await callMcpSourceTool(source, input.projectRoot, req.tool, req.args);
2446
+ return { ok: result.ok, text: result.text };
2447
+ });
2448
+ return { sourceId: source.id, tool, exclude, call };
2449
+ }
2450
+ function openMcpSearchProvider(input) {
2451
+ const timeoutMs = input.timeoutMs ?? mcpTimeoutMs();
2452
+ let ready3;
2453
+ async function load() {
2454
+ if (ready3) return ready3;
2455
+ ready3 = await connect(input);
2456
+ return ready3;
2457
+ }
2458
+ return {
2459
+ id: "mcp",
2460
+ async index(changed) {
2461
+ const session = await load();
2462
+ if (!changed) return emptyStats();
2463
+ const paths = allowedPaths(changed, session.exclude);
2464
+ if (paths.length === 0) return emptyStats(changed.length);
2465
+ const result = await withTimeout(
2466
+ session.call({ sourceId: session.sourceId, tool: session.tool, args: { paths } }),
2467
+ timeoutMs
2468
+ );
2469
+ if (!result.ok) throw new McpSearchError();
2470
+ return emptyStats(changed.length, paths.length);
2471
+ },
2472
+ async search(query, options) {
2473
+ const session = await load();
2474
+ const args = { query, scope: options.scope };
2475
+ const result = await withTimeout(
2476
+ session.call({ sourceId: session.sourceId, tool: session.tool, args }),
2477
+ timeoutMs
2478
+ );
2479
+ if (!result.ok) throw new McpSearchError();
2480
+ const hits = parseHits(result.text, options.scope, session.exclude);
2481
+ const preamble = searchPreamble(query, options.scope, options.budget, false, "mcp");
2482
+ const packed = packHits({ preamble, hits, budget: options.budget });
2483
+ return {
2484
+ provider: "mcp",
2485
+ query,
2486
+ scope: options.scope,
2487
+ budget: options.budget,
2488
+ usedTokens: packed.usedTokens,
2489
+ hits: packed.hits,
2490
+ text: packed.text
2491
+ };
2492
+ },
2493
+ stats() {
2494
+ return Promise.resolve(emptyStats());
2495
+ }
2496
+ };
2497
+ }
2498
+
2334
2499
  // src/search/registry.ts
2335
2500
  var extra = /* @__PURE__ */ new Map();
2336
2501
  function registerSearchProvider(provider) {
@@ -2347,13 +2512,18 @@ function joinWarning(left, right) {
2347
2512
  ${right}`;
2348
2513
  return left || right;
2349
2514
  }
2350
- function resolveSearchProvider(projectRoot, config, search, runtime) {
2515
+ function resolveSearchProvider(projectRoot, config, search, runtime, run) {
2351
2516
  const builtin = createBuiltinProvider(projectRoot, config, runtime);
2352
2517
  const name = search.provider || "builtin";
2353
2518
  if (name === "builtin") return builtin;
2354
2519
  const registered = extra.get(name);
2355
- let active = registered ?? builtin;
2356
- let warning = registered ? void 0 : fallbackWarning(name);
2520
+ let active = name === "mcp" ? openMcpSearchProvider({
2521
+ projectRoot,
2522
+ search,
2523
+ call: run?.mcpCall,
2524
+ timeoutMs: run?.mcpTimeoutMs
2525
+ }) : registered ?? builtin;
2526
+ let warning = name === "mcp" || registered ? void 0 : fallbackWarning(name);
2357
2527
  const mark = () => {
2358
2528
  warning = fallbackWarning(name);
2359
2529
  active = builtin;
@@ -2373,7 +2543,6 @@ function resolveSearchProvider(projectRoot, config, search, runtime) {
2373
2543
  try {
2374
2544
  const result = await active.search(query, options);
2375
2545
  result.warning = joinWarning(warning, result.warning);
2376
- result.provider = "builtin";
2377
2546
  return result;
2378
2547
  } catch (err) {
2379
2548
  if (active.id === "builtin") throw err;
@@ -2404,12 +2573,11 @@ async function buildRetrievedInner(projectRoot, config, title, stage, budget, ru
2404
2573
  return `Retrieved context skipped: ${safeMessage(err, projectRoot)}.`;
2405
2574
  }
2406
2575
  const limit = budget ?? budgetForStage(search, stage);
2407
- const provider = resolveSearchProvider(projectRoot, config, search, runtime);
2576
+ const provider = createBuiltinProvider(projectRoot, config, runtime);
2408
2577
  try {
2409
2578
  await provider.index();
2410
2579
  } catch (err) {
2411
- const message = provider.id === "builtin" ? safeMessage(err, projectRoot) : fallbackWarning(search.provider);
2412
- return `Retrieved context skipped: ${message}.`;
2580
+ return `Retrieved context skipped: ${safeMessage(err, projectRoot)}.`;
2413
2581
  }
2414
2582
  const request = {
2415
2583
  projectRoot,
@@ -2456,13 +2624,12 @@ async function buildRetrievedInner(projectRoot, config, title, stage, budget, ru
2456
2624
  }
2457
2625
  return packed.text;
2458
2626
  } catch (err) {
2459
- const message = search.provider === "builtin" ? safeMessage(err, projectRoot) : fallbackWarning(search.provider);
2460
- return `Retrieved context skipped: ${message}.`;
2627
+ return `Retrieved context skipped: ${safeMessage(err, projectRoot)}.`;
2461
2628
  }
2462
2629
  }
2463
- async function executeSearch(projectRoot, config, query, scope, budget) {
2630
+ async function executeSearch(projectRoot, config, query, scope, budget, run) {
2464
2631
  const search = await loadSearchConfig(projectRoot);
2465
- const provider = resolveSearchProvider(projectRoot, config, search);
2632
+ const provider = resolveSearchProvider(projectRoot, config, search, void 0, run);
2466
2633
  await provider.index();
2467
2634
  const options = {
2468
2635
  scope,
@@ -2668,7 +2835,7 @@ function stringList(value) {
2668
2835
  }
2669
2836
  return out;
2670
2837
  }
2671
- function parseRoleDocument(name, raw) {
2838
+ function splitFrontmatter(raw) {
2672
2839
  const text = raw.replace(/^\uFEFF/, "");
2673
2840
  const nl = text.indexOf("\n");
2674
2841
  if (nl < 0 || text.slice(0, nl).trim() !== "---") return null;
@@ -2682,14 +2849,22 @@ function parseRoleDocument(name, raw) {
2682
2849
  return null;
2683
2850
  }
2684
2851
  if (!data || typeof data !== "object" || Array.isArray(data)) return null;
2685
- const rec = data;
2852
+ return {
2853
+ data,
2854
+ body: rest.slice(close.index + close[0].length).trim()
2855
+ };
2856
+ }
2857
+ function parseRoleDocument(name, raw) {
2858
+ const split = splitFrontmatter(raw);
2859
+ if (!split) return null;
2860
+ const rec = split.data;
2686
2861
  const lists = emptyRoleLists();
2687
2862
  for (const [field2, key] of LIST_FIELDS) {
2688
2863
  const parsed = stringList(rec[key]);
2689
2864
  if (!parsed) return null;
2690
2865
  lists[field2] = parsed;
2691
2866
  }
2692
- const body = rest.slice(close.index + close[0].length).trim();
2867
+ const body = split.body;
2693
2868
  return {
2694
2869
  name,
2695
2870
  label: asText(rec.label),
@@ -2701,7 +2876,7 @@ function parseRoleDocument(name, raw) {
2701
2876
  ...lists
2702
2877
  };
2703
2878
  }
2704
- function renderRole(role) {
2879
+ function renderRole(role, routines) {
2705
2880
  const record = {
2706
2881
  name: role.name,
2707
2882
  label: role.label,
@@ -2710,6 +2885,7 @@ function renderRole(role) {
2710
2885
  pinned: role.pinned,
2711
2886
  hidden: role.hidden
2712
2887
  };
2888
+ if (routines?.keep) record.routines = routines.value;
2713
2889
  for (const [field2, key] of LIST_FIELDS) {
2714
2890
  if (role[field2].length > 0) record[key] = role[field2];
2715
2891
  }
@@ -2748,8 +2924,15 @@ async function readRole(root, name) {
2748
2924
  return null;
2749
2925
  }
2750
2926
  }
2751
- async function writeRole(root, role) {
2752
- await writeText(roleFilePath(root, role.name), renderRole(role));
2927
+ async function keptRoutines(root, name) {
2928
+ const path = roleFilePath(root, name);
2929
+ if (!await pathExists(path)) return void 0;
2930
+ const split = splitFrontmatter(await readText(path));
2931
+ if (!split || !Object.hasOwn(split.data, "routines")) return void 0;
2932
+ return { keep: true, value: split.data.routines };
2933
+ }
2934
+ async function writeRole(root, role, routines) {
2935
+ await writeText(roleFilePath(root, role.name), renderRole(role, routines));
2753
2936
  }
2754
2937
  async function createRole(root, input) {
2755
2938
  const name = canonicalRoleName(input.name);
@@ -2784,7 +2967,7 @@ async function editRole(root, nameInput, patch) {
2784
2967
  if (patch.description !== void 0) role.description = patch.description.trim();
2785
2968
  if (patch.askFirst !== void 0) role.askFirst = patch.askFirst;
2786
2969
  if (patch.stages !== void 0) role.stages = patch.stages;
2787
- await writeRole(root, role);
2970
+ await writeRole(root, role, await keptRoutines(root, name));
2788
2971
  return ok();
2789
2972
  }
2790
2973
  async function setFlag(root, nameInput, flag) {
@@ -2793,7 +2976,7 @@ async function setFlag(root, nameInput, flag) {
2793
2976
  const role = await readRole(root, name);
2794
2977
  if (!role) return fail(ROLE_TEXT.notFound);
2795
2978
  role[flag] = true;
2796
- await writeRole(root, role);
2979
+ await writeRole(root, role, await keptRoutines(root, name));
2797
2980
  return ok();
2798
2981
  }
2799
2982
  function pinRole(root, name) {
@@ -2836,7 +3019,7 @@ async function duplicateRole(root, nameInput) {
2836
3019
  const copyName = canonicalRoleName(`${name} copy`);
2837
3020
  if (!copyName) return fail(ROLE_TEXT.badName);
2838
3021
  if (await pathExists(roleFilePath(root, copyName))) return fail(ROLE_TEXT.exists);
2839
- await writeRole(root, { ...source, name: copyName });
3022
+ await writeRole(root, { ...source, name: copyName }, await keptRoutines(root, name));
2840
3023
  return ok();
2841
3024
  }
2842
3025
  async function deleteRole(root, nameInput) {
@@ -3321,9 +3504,9 @@ async function buildAgentPrompt(ctx, config, projectRoot, budget, runtime) {
3321
3504
  parts.push("");
3322
3505
  }
3323
3506
  try {
3324
- const { loadMcpConfig } = await import("./sources-3TXUPU6V.js");
3325
- const { gatherMcpContextForChange, formatMcpContextForHandoff } = await import("./gather-A3Q4WSPH.js");
3326
- const mcpCfg = await loadMcpConfig(projectRoot);
3507
+ const { loadMcpConfig: loadMcpConfig2 } = await import("./sources-3TXUPU6V.js");
3508
+ const { gatherMcpContextForChange, formatMcpContextForHandoff } = await import("./gather-DDUZEIQZ.js");
3509
+ const mcpCfg = await loadMcpConfig2(projectRoot);
3327
3510
  if (mcpCfg.auto_fetch_on_handoff && mcpCfg.sources.length) {
3328
3511
  const fetched = await gatherMcpContextForChange(projectRoot, ctx);
3329
3512
  const block = formatMcpContextForHandoff(fetched.filter((r) => r.ok || r.error));
@@ -3414,6 +3597,7 @@ export {
3414
3597
  listScopeHits,
3415
3598
  rankScope,
3416
3599
  searchProject,
3600
+ openMcpSearchProvider,
3417
3601
  registerSearchProvider,
3418
3602
  clearRegisteredSearchProviders,
3419
3603
  fallbackWarning,
@@ -3429,6 +3613,7 @@ export {
3429
3613
  conversationDir,
3430
3614
  memoryDir,
3431
3615
  allowFilePath,
3616
+ splitFrontmatter,
3432
3617
  parseRoleDocument,
3433
3618
  rolesListingStage,
3434
3619
  readRole,
@@ -3,9 +3,9 @@ import {
3
3
  gatherMcpContext,
4
4
  gatherMcpContextForChange,
5
5
  listMatchingSourceIds
6
- } from "./chunk-ICRQOQWE.js";
6
+ } from "./chunk-PFJFWZOM.js";
7
+ import "./chunk-OY47H6R5.js";
7
8
  import "./chunk-4BRO7BOJ.js";
8
- import "./chunk-MHODNFIL.js";
9
9
  import "./chunk-O5SP6X5R.js";
10
10
  export {
11
11
  formatMcpContextForHandoff,
@@ -6,10 +6,11 @@ import {
6
6
  startFeatureFromBacklog,
7
7
  startGreenfield,
8
8
  updateFeatureStatus
9
- } from "./chunk-Z2ULYVHO.js";
10
- import "./chunk-AERAWOAK.js";
9
+ } from "./chunk-KMITXC7I.js";
10
+ import "./chunk-RXQH2THQ.js";
11
11
  import "./chunk-TNWFMRIA.js";
12
- import "./chunk-MHODNFIL.js";
12
+ import "./chunk-OY47H6R5.js";
13
+ import "./chunk-4BRO7BOJ.js";
13
14
  import "./chunk-O5SP6X5R.js";
14
15
  export {
15
16
  findFeaturesBacklogPath,
package/dist/index.d.ts CHANGED
@@ -1770,6 +1770,8 @@ declare const SearchConfigSchema: z.ZodObject<{
1770
1770
  default: z.ZodDefault<z.ZodNumber>;
1771
1771
  }, z.ZodNumber, "strip">>>;
1772
1772
  exclude: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1773
+ mcp_source: z.ZodOptional<z.ZodString>;
1774
+ mcp_tool: z.ZodOptional<z.ZodString>;
1773
1775
  }, "strip", z.ZodTypeAny, {
1774
1776
  version: 1;
1775
1777
  exclude: string[];
@@ -1781,6 +1783,8 @@ declare const SearchConfigSchema: z.ZodObject<{
1781
1783
  } & {
1782
1784
  [k: string]: number;
1783
1785
  };
1786
+ mcp_source?: string | undefined;
1787
+ mcp_tool?: string | undefined;
1784
1788
  }, {
1785
1789
  version?: 1 | undefined;
1786
1790
  exclude?: string[] | undefined;
@@ -1790,6 +1794,8 @@ declare const SearchConfigSchema: z.ZodObject<{
1790
1794
  budgets?: z.objectInputType<{
1791
1795
  default: z.ZodDefault<z.ZodNumber>;
1792
1796
  }, z.ZodNumber, "strip"> | undefined;
1797
+ mcp_source?: string | undefined;
1798
+ mcp_tool?: string | undefined;
1793
1799
  }>;
1794
1800
  type SearchConfig = z.infer<typeof SearchConfigSchema>;
1795
1801
  declare function budgetForStage(config: SearchConfig, stage: string | undefined): number;
@@ -1821,7 +1827,7 @@ interface SearchHit {
1821
1827
  language: string;
1822
1828
  }
1823
1829
  interface SearchResult {
1824
- provider: "builtin";
1830
+ provider: string;
1825
1831
  warning?: string;
1826
1832
  query: string;
1827
1833
  scope: SearchScope;
@@ -1831,7 +1837,7 @@ interface SearchResult {
1831
1837
  text: string;
1832
1838
  }
1833
1839
  interface IndexStats {
1834
- provider: "builtin";
1840
+ provider: string;
1835
1841
  files: number;
1836
1842
  chunks: number;
1837
1843
  lastIndexFilesConsidered: number;
@@ -1862,7 +1868,7 @@ interface RawHit {
1862
1868
  summary?: string;
1863
1869
  }
1864
1870
 
1865
- declare function searchPreamble(query: string, scope: string, budget: number, hybrid?: boolean): string;
1871
+ declare function searchPreamble(query: string, scope: string, budget: number, hybrid?: boolean, provider?: string): string;
1866
1872
  declare function renderBlock(hit: RawHit, form: "full" | "signature" | "summary"): string;
1867
1873
  declare function packHits(input: {
1868
1874
  preamble: string;
@@ -1985,12 +1991,32 @@ declare function fuseHits(keyword: readonly RawHit[], vector: readonly RawHit[])
1985
1991
  */
1986
1992
  declare function mergeRankedHits(hits: readonly RawHit[]): RawHit[];
1987
1993
 
1994
+ interface McpToolResult {
1995
+ ok: boolean;
1996
+ text: string;
1997
+ }
1998
+ type McpSearchCall = (input: {
1999
+ sourceId: string;
2000
+ tool: string;
2001
+ args: Record<string, unknown>;
2002
+ }) => Promise<McpToolResult>;
2003
+ interface SearchRunOptions {
2004
+ mcpCall?: McpSearchCall;
2005
+ mcpTimeoutMs?: number;
2006
+ }
2007
+ declare function openMcpSearchProvider(input: {
2008
+ projectRoot: string;
2009
+ search: SearchConfig;
2010
+ call?: McpSearchCall;
2011
+ timeoutMs?: number;
2012
+ }): SearchProvider;
2013
+
1988
2014
  declare function registerSearchProvider(provider: SearchProvider): void;
1989
2015
  declare function clearRegisteredSearchProviders(): void;
1990
2016
  declare function fallbackWarning(name: string): string;
1991
- declare function resolveSearchProvider(projectRoot: string, config: Config, search: SearchConfig, runtime?: SearchRuntime): SearchProvider;
2017
+ declare function resolveSearchProvider(projectRoot: string, config: Config, search: SearchConfig, runtime?: SearchRuntime, run?: SearchRunOptions): SearchProvider;
1992
2018
  declare function buildRetrievedInner(projectRoot: string, config: Config, title: string, stage: string | undefined, budget: number | undefined, runtime?: SearchRuntime, activeChange?: string): Promise<string>;
1993
- declare function executeSearch(projectRoot: string, config: Config, query: string, scope: SearchScope, budget: number | undefined): Promise<SearchResult>;
2019
+ declare function executeSearch(projectRoot: string, config: Config, query: string, scope: SearchScope, budget: number | undefined, run?: SearchRunOptions): Promise<SearchResult>;
1994
2020
 
1995
2021
  interface SyncChangeResult {
1996
2022
  changeId: string;
@@ -3351,6 +3377,32 @@ declare function rebuildNetwork(root: string, input: {
3351
3377
  now?: () => Date;
3352
3378
  }): Promise<RoleCommandResult>;
3353
3379
 
3380
+ interface IssueRecord {
3381
+ number: number;
3382
+ title: string;
3383
+ state: string;
3384
+ }
3385
+ type IssueRead = {
3386
+ ok: true;
3387
+ issue: IssueRecord;
3388
+ } | {
3389
+ ok: false;
3390
+ missing: boolean;
3391
+ };
3392
+ interface IssueSource {
3393
+ read(number: number): Promise<IssueRead>;
3394
+ }
3395
+ declare function ghIssueSource(): IssueSource;
3396
+ declare function readConnector(input: {
3397
+ verb: string;
3398
+ connector: string;
3399
+ record: string;
3400
+ source?: IssueSource;
3401
+ projectRoot?: string;
3402
+ config?: Config;
3403
+ }): Promise<RoleCommandResult>;
3404
+ declare function runRoutine(root: string, roleName: string, routineName: string, source?: IssueSource): Promise<RoleCommandResult>;
3405
+
3354
3406
  interface RunRoleInput {
3355
3407
  name: string;
3356
3408
  task?: string;
@@ -4031,4 +4083,4 @@ declare function formatEpicGraph(nodes: StoryNode[]): {
4031
4083
  /** Graph errors, then open dependencies. Null means the branch may be created. */
4032
4084
  declare function branchBlock(nodes: StoryNode[], story: string): string | null;
4033
4085
 
4034
- export { AGENT_INTEGRATIONS, AGENT_TARGET_OPTIONS, ALL_AGENT_TARGETS, type AdapterExtractResult, AdapterRegistry, type AdvanceResult, type AgentInstallPlan, AgentInstallPreflightError, type AgentIntegration, type AgentTarget, type AgentTargetOption, type AllowRoleInput, type ArtifactDef, ArtifactDefSchema, type BuildRefinePlanOptions, type CallMcpToolResult, type ChangeContext, type ChangeMeta, ChangeMetaSchema, type ChangeMetrics, ChangeMetricsSchema, type ChangePhaseOrder, type CodeContextCaps, type CodeContextGap, type CodeContextGapCode, type CodeContextRequest, type CodeContextResult, type CodeContextSummary, type CodeSlice, type Complexity, type Config, ConfigSchema, type CreateChangeInput, DEFAULT_CODE_CONTEXT_CAPS, DEFAULT_INIT_INTEGRATION, type DecideInput, type DecisionMetric, DecisionMetricSchema, type DecisionModel, type DecisionOutcome, type Duty, EMBEDDINGS_UNAVAILABLE, EMBEDDING_MODEL, type Embedder, type FastembedHooks, type FocusPlan, type Gate, GateSchema, type GatherMcpOptions, type GenerateCodeContextDeps, type GeneratedManifest, type GeneratedState, type GitHeadRunner, type GreenfieldFeature, type IndexStats, type InitOptions, type InitResult, type InstallAgentOptions, type InstallAgentResult, type InstallAgentsOptions, type InstallAgentsResult, type InstalledAgentSnapshot, type KeptFile, type KeptReason, type LanguageAdapter, type McpConfig, McpConfigSchema, type McpFetchResult, type McpInvoke, McpInvokeSchema, type McpMatchContext, type McpSource, McpSourceSchema, type McpWhen, McpWhenSchema, type MetricsImportResult, type ModelChoice, type ModelContext, type ModelEntry, type ModelsConfig, ModelsConfigSchema, PROTOCOL_MD, type PhaseMetric, PhaseMetricSchema, type PhaseTiming, type PhaseTimingRow, type PlannedWrite, type PriceCard, type Prices, type ProductTeamMember, RRF_K, type RawHit, type ReconcileGeneratedResult, type RefineArtifactRef, type RefineMode, type RefinePlan, type RemoveAgentHostsResult, type RenderChangeReportInput, type RoleCommandResult, type RoleLists, type RoleModel, type RoleProfile, type RouteDeps, type RouteHit, type RouteItem, type RunRoleInput, SDD_AGENT_ROLES, SDD_CORE_VERSION, SDD_DIR, SETUP_STEP_IDS, SETUP_WHY, SUMMARY_TOKEN_CAP, type SddAgentRole, type SddAgentRoleId, SddError, type SearchConfig, SearchConfigError, type SearchHit, type SearchProvider, type SearchQuery, type SearchResult, type SearchRuntime, type SearchScope, type SetupModelState, type SetupRolesChoice, type SetupStatus, type SetupStepId, type SetupStepInput, type Stage, StageSchema, type StartFeatureInput, type StartGreenfieldInput, type StartGreenfieldResult, type StoryDraft, type StoryNode, type SymbolInfo, type SymbolKind, type SyncChangeResult, type TeamConfig, TeamSchema, type TokenCounts, type TokenUsageMetric, TokenUsageMetricSchema, VerifyCommandSchema, type VerifyResult, type VerifyStatus, WORK_TYPES, type WorkType, type Workflow, WorkflowSchema, acceptNetwork, activePointerPath, activeStages, addLesson, addMcpSource, advanceStage, agentHostPaths, agentKickoffMessage, allowRole, approveGate, archiveDir, assertAgentInstallable, assertSessionLogAllowed, branchBlock, budgetForStage, buildAgentPrompt, buildContext, buildRefinePlan, buildRetrievedInner, callMcpSourceTool, canLeaveStage, changeDirName, changeMetaPath, changePath, changesDir, changesPathRel, checkModels, checkTeam, chunkCode, chunkMarkdown, classifyPath, clearActiveIf, clearRegisteredSearchProviders, compareChangesByFirstPhase, completeChange, configPath, contentHash, copyDir, copyDirSkipExisting, costFor, countTokens, createBuiltinProvider, createChange, createFastembedEmbedder, createRole, createRoleFromTemplate, decide, defaultConfig, defaultMcpConfig, defaultMcpYamlPath, defaultMemoryDir, defaultPricesYamlPath, defaultSearchYamlPath, defaultTeamsDir, defaultTemplatesDir, defaultWorkflowsDir, defaultsRoot, deleteRole, describeFsError, describeKept, displayArchivePath, displayChangePath, domainsDir, duplicateRole, dutyForStage, editRole, embedSearchQuery, emptyChangeMetrics, ensureDir, ensureMcpConfig, errorMessage, executeSearch, explainMatch, explainModel, extractiveSummary, fallbackAdapter, fallbackIncompleteStageId, fallbackWarning, fastembedImportCount, findFeaturesBacklogPath, firstActiveStageId, formatDuration, formatEpicGraph, formatJsonSummary, formatMcpContextForHandoff, formatModels, formatSetupStatus, formatStatus, formatTeam, formatTokenInventory, ftsTokens, fuseByRank, fuseHits, gatherMcpContext, gatherMcpContextForChange, generateCodeContext, generatedState, getActiveChangeId, getFacts, getHeadSha, getIntegration, getStage, gitUserName, guidancePaths, handoffRole, hideRole, importSessionMetrics, incompletePriorStageErrors, indexDbPath, inferComplexity, initProject, initTeam, installAgentIntegration, installAgentIntegrations, integrationKeyFor, interpolate, interpolateArgs, isHardDenied, isIgnoredPath, isInitialized, isPrunedDir, isSddError, isSecretPath, isStageSkipped, isSubstantiveArtifactContent, isWorkType, keywordHits, listBacklogFeatures, listBundledWorkflowNames, listChanges, listDirs, listFacts, listFiles, listMatchingSourceIds, listMcpSourceTools, listRoleTemplates, listScopeHits, listTeamTemplates, listWorkflowNames, loadBrain, loadChangeMeta, loadConfig, loadEpicStories, loadExcluder, loadGeneratedManifest, loadInstalledAgent, loadMcpConfig, loadModels, loadPrices, loadProductTeam, loadSearchConfig, loadWorkflow, markGenerated, matchMcpSources, mcpConfigPath, mcpTimeoutMs, memoryDir, memoryPathRel, mergeCaps, mergeConfigDefaults, mergeRankedHits, migrateTeamMemory, missingBundledWorkflows, modelFromEnv, nextStageId, nowIso, optionForTarget, packHits, parseAgentTargets, parseFeaturesBacklog, parseIntegration, parseSetupStep, parseStoryDraft, pathExists, phaseTiming, pinRole, planAgentIntegration, planNetwork, postRoom, prepareGuide, productTeamHome, promoteGreenfieldToMemory, queueRole, rankScope, readChangeMetrics, readHandoffCodePoints, readSetupStatus, readTeamConfig, readText, readYaml, rebuildNetwork, recommendWorkflow, reconcileGeneratedTree, recordDecisionMetric, recordDecisionRequest, recordSignoff, refreshActiveAgentContext, refreshConfiguredGuidance, registerSearchProvider, removeMcpSource, removeOtherAgentHosts, removeOtherAgentHostsDetailed, removePath, renderAgentsMd, renderBlock, renderChangeReport, renderMemoryIndex, renderProductTeamSection, renderProtocolMd, renderSddReadme, renderThinAgent, repairRequiredIgnores, reportAllChanges, reportChange, resolveActiveDirectory, resolveBot, resolveChangeId, resolveEmbedder, resolveFocus, resolveSearchProvider, resolveStages, reviewRoom, roleContextBody, routeRole, rrf, runGuide, runLocalVerify, runLoop, runNetwork, runRole, runSetupStep, saveChangeMeta, saveConfig, saveGeneratedManifest, saveMcpConfig, scopeForPath, sddRoot, searchConfigPath, searchPreamble, selectModel, setActiveChange, setFact, setRoleContext, setRoleMessaging, shouldAutoSkip, showFact, showMemory, showRoleGroup, showRoles, showRoom, showTeam, skipStage, slugify, spawnModelCommand, startFeatureFromBacklog, startGreenfield, startPhase, storyIdTaken, switchWorkflow, syncChangeHead, takeRole, templatesDir, toProcessEnv, todayIsoDate, tokenizeKeywords, transitionPhase, typescriptAdapter, uniqueChangeDirName, updateFeatureStatus, validBranchName, withMcpSource, workKind, workflowUnavailableMessage, workflowsDir, writeAgentHandoff, writeRefineBrief, writeText, writeTextIfMissing, writeYaml };
4086
+ export { AGENT_INTEGRATIONS, AGENT_TARGET_OPTIONS, ALL_AGENT_TARGETS, type AdapterExtractResult, AdapterRegistry, type AdvanceResult, type AgentInstallPlan, AgentInstallPreflightError, type AgentIntegration, type AgentTarget, type AgentTargetOption, type AllowRoleInput, type ArtifactDef, ArtifactDefSchema, type BuildRefinePlanOptions, type CallMcpToolResult, type ChangeContext, type ChangeMeta, ChangeMetaSchema, type ChangeMetrics, ChangeMetricsSchema, type ChangePhaseOrder, type CodeContextCaps, type CodeContextGap, type CodeContextGapCode, type CodeContextRequest, type CodeContextResult, type CodeContextSummary, type CodeSlice, type Complexity, type Config, ConfigSchema, type CreateChangeInput, DEFAULT_CODE_CONTEXT_CAPS, DEFAULT_INIT_INTEGRATION, type DecideInput, type DecisionMetric, DecisionMetricSchema, type DecisionModel, type DecisionOutcome, type Duty, EMBEDDINGS_UNAVAILABLE, EMBEDDING_MODEL, type Embedder, type FastembedHooks, type FocusPlan, type Gate, GateSchema, type GatherMcpOptions, type GenerateCodeContextDeps, type GeneratedManifest, type GeneratedState, type GitHeadRunner, type GreenfieldFeature, type IndexStats, type InitOptions, type InitResult, type InstallAgentOptions, type InstallAgentResult, type InstallAgentsOptions, type InstallAgentsResult, type InstalledAgentSnapshot, type IssueRead, type IssueRecord, type IssueSource, type KeptFile, type KeptReason, type LanguageAdapter, type McpConfig, McpConfigSchema, type McpFetchResult, type McpInvoke, McpInvokeSchema, type McpMatchContext, type McpSearchCall, type McpSource, McpSourceSchema, type McpToolResult, type McpWhen, McpWhenSchema, type MetricsImportResult, type ModelChoice, type ModelContext, type ModelEntry, type ModelsConfig, ModelsConfigSchema, PROTOCOL_MD, type PhaseMetric, PhaseMetricSchema, type PhaseTiming, type PhaseTimingRow, type PlannedWrite, type PriceCard, type Prices, type ProductTeamMember, RRF_K, type RawHit, type ReconcileGeneratedResult, type RefineArtifactRef, type RefineMode, type RefinePlan, type RemoveAgentHostsResult, type RenderChangeReportInput, type RoleCommandResult, type RoleLists, type RoleModel, type RoleProfile, type RouteDeps, type RouteHit, type RouteItem, type RunRoleInput, SDD_AGENT_ROLES, SDD_CORE_VERSION, SDD_DIR, SETUP_STEP_IDS, SETUP_WHY, SUMMARY_TOKEN_CAP, type SddAgentRole, type SddAgentRoleId, SddError, type SearchConfig, SearchConfigError, type SearchHit, type SearchProvider, type SearchQuery, type SearchResult, type SearchRunOptions, type SearchRuntime, type SearchScope, type SetupModelState, type SetupRolesChoice, type SetupStatus, type SetupStepId, type SetupStepInput, type Stage, StageSchema, type StartFeatureInput, type StartGreenfieldInput, type StartGreenfieldResult, type StoryDraft, type StoryNode, type SymbolInfo, type SymbolKind, type SyncChangeResult, type TeamConfig, TeamSchema, type TokenCounts, type TokenUsageMetric, TokenUsageMetricSchema, VerifyCommandSchema, type VerifyResult, type VerifyStatus, WORK_TYPES, type WorkType, type Workflow, WorkflowSchema, acceptNetwork, activePointerPath, activeStages, addLesson, addMcpSource, advanceStage, agentHostPaths, agentKickoffMessage, allowRole, approveGate, archiveDir, assertAgentInstallable, assertSessionLogAllowed, branchBlock, budgetForStage, buildAgentPrompt, buildContext, buildRefinePlan, buildRetrievedInner, callMcpSourceTool, canLeaveStage, changeDirName, changeMetaPath, changePath, changesDir, changesPathRel, checkModels, checkTeam, chunkCode, chunkMarkdown, classifyPath, clearActiveIf, clearRegisteredSearchProviders, compareChangesByFirstPhase, completeChange, configPath, contentHash, copyDir, copyDirSkipExisting, costFor, countTokens, createBuiltinProvider, createChange, createFastembedEmbedder, createRole, createRoleFromTemplate, decide, defaultConfig, defaultMcpConfig, defaultMcpYamlPath, defaultMemoryDir, defaultPricesYamlPath, defaultSearchYamlPath, defaultTeamsDir, defaultTemplatesDir, defaultWorkflowsDir, defaultsRoot, deleteRole, describeFsError, describeKept, displayArchivePath, displayChangePath, domainsDir, duplicateRole, dutyForStage, editRole, embedSearchQuery, emptyChangeMetrics, ensureDir, ensureMcpConfig, errorMessage, executeSearch, explainMatch, explainModel, extractiveSummary, fallbackAdapter, fallbackIncompleteStageId, fallbackWarning, fastembedImportCount, findFeaturesBacklogPath, firstActiveStageId, formatDuration, formatEpicGraph, formatJsonSummary, formatMcpContextForHandoff, formatModels, formatSetupStatus, formatStatus, formatTeam, formatTokenInventory, ftsTokens, fuseByRank, fuseHits, gatherMcpContext, gatherMcpContextForChange, generateCodeContext, generatedState, getActiveChangeId, getFacts, getHeadSha, getIntegration, getStage, ghIssueSource, gitUserName, guidancePaths, handoffRole, hideRole, importSessionMetrics, incompletePriorStageErrors, indexDbPath, inferComplexity, initProject, initTeam, installAgentIntegration, installAgentIntegrations, integrationKeyFor, interpolate, interpolateArgs, isHardDenied, isIgnoredPath, isInitialized, isPrunedDir, isSddError, isSecretPath, isStageSkipped, isSubstantiveArtifactContent, isWorkType, keywordHits, listBacklogFeatures, listBundledWorkflowNames, listChanges, listDirs, listFacts, listFiles, listMatchingSourceIds, listMcpSourceTools, listRoleTemplates, listScopeHits, listTeamTemplates, listWorkflowNames, loadBrain, loadChangeMeta, loadConfig, loadEpicStories, loadExcluder, loadGeneratedManifest, loadInstalledAgent, loadMcpConfig, loadModels, loadPrices, loadProductTeam, loadSearchConfig, loadWorkflow, markGenerated, matchMcpSources, mcpConfigPath, mcpTimeoutMs, memoryDir, memoryPathRel, mergeCaps, mergeConfigDefaults, mergeRankedHits, migrateTeamMemory, missingBundledWorkflows, modelFromEnv, nextStageId, nowIso, openMcpSearchProvider, optionForTarget, packHits, parseAgentTargets, parseFeaturesBacklog, parseIntegration, parseSetupStep, parseStoryDraft, pathExists, phaseTiming, pinRole, planAgentIntegration, planNetwork, postRoom, prepareGuide, productTeamHome, promoteGreenfieldToMemory, queueRole, rankScope, readChangeMetrics, readConnector, readHandoffCodePoints, readSetupStatus, readTeamConfig, readText, readYaml, rebuildNetwork, recommendWorkflow, reconcileGeneratedTree, recordDecisionMetric, recordDecisionRequest, recordSignoff, refreshActiveAgentContext, refreshConfiguredGuidance, registerSearchProvider, removeMcpSource, removeOtherAgentHosts, removeOtherAgentHostsDetailed, removePath, renderAgentsMd, renderBlock, renderChangeReport, renderMemoryIndex, renderProductTeamSection, renderProtocolMd, renderSddReadme, renderThinAgent, repairRequiredIgnores, reportAllChanges, reportChange, resolveActiveDirectory, resolveBot, resolveChangeId, resolveEmbedder, resolveFocus, resolveSearchProvider, resolveStages, reviewRoom, roleContextBody, routeRole, rrf, runGuide, runLocalVerify, runLoop, runNetwork, runRole, runRoutine, runSetupStep, saveChangeMeta, saveConfig, saveGeneratedManifest, saveMcpConfig, scopeForPath, sddRoot, searchConfigPath, searchPreamble, selectModel, setActiveChange, setFact, setRoleContext, setRoleMessaging, shouldAutoSkip, showFact, showMemory, showRoleGroup, showRoles, showRoom, showTeam, skipStage, slugify, spawnModelCommand, startFeatureFromBacklog, startGreenfield, startPhase, storyIdTaken, switchWorkflow, syncChangeHead, takeRole, templatesDir, toProcessEnv, todayIsoDate, tokenizeKeywords, transitionPhase, typescriptAdapter, uniqueChangeDirName, updateFeatureStatus, validBranchName, withMcpSource, workKind, workflowUnavailableMessage, workflowsDir, writeAgentHandoff, writeRefineBrief, writeText, writeTextIfMissing, writeYaml };