kirograph 1.2.3 → 1.4.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.
Files changed (50) hide show
  1. package/README.md +5 -3
  2. package/dist/bin/commands/attack-surface.js +17 -2
  3. package/dist/bin/commands/attack-surface.js.map +2 -2
  4. package/dist/bin/commands/help.js +4 -2
  5. package/dist/bin/commands/help.js.map +2 -2
  6. package/dist/bin/commands/memory.js +23 -3
  7. package/dist/bin/commands/memory.js.map +2 -2
  8. package/dist/bin/commands/security-export.js +9 -1
  9. package/dist/bin/commands/security-export.js.map +2 -2
  10. package/dist/bin/commands/wiki.js +14 -1
  11. package/dist/bin/commands/wiki.js.map +2 -2
  12. package/dist/bin/installer/common.js +25 -0
  13. package/dist/bin/installer/common.js.map +2 -2
  14. package/dist/bin/installer/config-prompt.js +29 -1
  15. package/dist/bin/installer/config-prompt.js.map +2 -2
  16. package/dist/bin/installer/index.js +49 -0
  17. package/dist/bin/installer/index.js.map +2 -2
  18. package/dist/bin/installer/steering.js +5 -1
  19. package/dist/bin/installer/steering.js.map +2 -2
  20. package/dist/bin/kirograph.js +1 -1
  21. package/dist/config.js +73 -2
  22. package/dist/config.js.map +2 -2
  23. package/dist/jev/client.js.map +2 -2
  24. package/dist/jev/factory.js +36 -0
  25. package/dist/jev/factory.js.map +7 -0
  26. package/dist/jev/strands-client.js +89 -0
  27. package/dist/jev/strands-client.js.map +7 -0
  28. package/dist/jev/types.js.map +1 -1
  29. package/dist/mcp/handlers/memory.js +18 -5
  30. package/dist/mcp/handlers/memory.js.map +2 -2
  31. package/dist/mcp/handlers/security.js +15 -2
  32. package/dist/mcp/handlers/security.js.map +2 -2
  33. package/dist/mcp/handlers/wiki.js +13 -1
  34. package/dist/mcp/handlers/wiki.js.map +2 -2
  35. package/dist/mcp/tools.js +4 -4
  36. package/dist/mcp/tools.js.map +2 -2
  37. package/dist/memory/index.js +42 -10
  38. package/dist/memory/index.js.map +2 -2
  39. package/dist/memory/relation-display.js +37 -0
  40. package/dist/memory/relation-display.js.map +7 -0
  41. package/dist/memory/relation-jev.js.map +1 -1
  42. package/dist/security/attack-surface.js +20 -2
  43. package/dist/security/attack-surface.js.map +2 -2
  44. package/dist/security/auth-detection-jev.js.map +1 -1
  45. package/dist/wiki/contradiction-jev.js.map +1 -1
  46. package/dist/wiki/index.js +21 -2
  47. package/dist/wiki/index.js.map +2 -2
  48. package/dist/wiki/lint.js +23 -11
  49. package/dist/wiki/lint.js.map +2 -2
  50. package/package.json +1 -1
package/dist/config.js CHANGED
@@ -81,6 +81,8 @@ const KNOWN_FIELDS = /* @__PURE__ */ new Set([
81
81
  "memoryContextThreshold",
82
82
  "memoryExcludePatterns",
83
83
  "memoryStrictWrites",
84
+ "memoryRelationMode",
85
+ "memoryRelationConfidenceThreshold",
84
86
  "memorySchemaValidation",
85
87
  "enableWatchmen",
86
88
  "watchmenThreshold",
@@ -95,6 +97,8 @@ const KNOWN_FIELDS = /* @__PURE__ */ new Set([
95
97
  "wikiLintFrequency",
96
98
  "wikiContextLimit",
97
99
  "wikiContextThreshold",
100
+ "wikiContradictionMode",
101
+ "wikiContradictionConfidenceThreshold",
98
102
  "enableDocs",
99
103
  "docsInclude",
100
104
  "docsExclude",
@@ -117,6 +121,8 @@ const KNOWN_FIELDS = /* @__PURE__ */ new Set([
117
121
  "securityAutoEnrich",
118
122
  "securityEnrichMaxAgeDays",
119
123
  "securityLicensePolicy",
124
+ "securityAuthDetectionMode",
125
+ "securityAuthConfidenceThreshold",
120
126
  "enablePatterns",
121
127
  "patternLibraryPath",
122
128
  "patternSeverityThreshold",
@@ -129,6 +135,11 @@ const KNOWN_FIELDS = /* @__PURE__ */ new Set([
129
135
  "enableAgentUtils",
130
136
  "enableGeneralCompression",
131
137
  "contextBudget",
138
+ "jevApiKey",
139
+ "jevBaseUrl",
140
+ "jevModel",
141
+ "strandsBaseUrl",
142
+ "strandsModel",
132
143
  // Legacy aliases / derived fields (accepted but ignored or recomputed)
133
144
  "enableCompression",
134
145
  "compressionLevel",
@@ -199,6 +210,8 @@ function createDefaultConfig(_projectRoot) {
199
210
  memoryContextThreshold: 0.3,
200
211
  memoryExcludePatterns: [],
201
212
  memoryStrictWrites: false,
213
+ memoryRelationMode: "agent",
214
+ memoryRelationConfidenceThreshold: 0.8,
202
215
  memorySchemaValidation: false,
203
216
  enableWatchmen: false,
204
217
  watchmenThreshold: 5,
@@ -213,6 +226,8 @@ function createDefaultConfig(_projectRoot) {
213
226
  wikiLintFrequency: "off",
214
227
  wikiContextLimit: 3,
215
228
  wikiContextThreshold: 0.4,
229
+ wikiContradictionMode: "heuristic",
230
+ wikiContradictionConfidenceThreshold: 0.7,
216
231
  enableDocs: false,
217
232
  docsInclude: ["**/*.md", "**/*.mdx", "**/*.rst", "**/*.adoc", "**/*.asciidoc", "**/*.rdoc", "**/*.org", "**/*.cheatmd", "docs/**/*.txt", "docs/**/*.html"],
218
233
  docsExclude: ["node_modules/**", "**/CHANGELOG*", "**/LICENSE*", "**/CHANGES*", "dist/**", "build/**", "coverage/**", ".git/**", "**/generated/**", "**/auto-generated/**", "**/vendor/**", "_build/**"],
@@ -234,6 +249,8 @@ function createDefaultConfig(_projectRoot) {
234
249
  securityDatabases: ["OSV"],
235
250
  securityAutoEnrich: true,
236
251
  securityEnrichMaxAgeDays: 7,
252
+ securityAuthDetectionMode: "heuristic",
253
+ securityAuthConfidenceThreshold: 0.6,
237
254
  securityLicensePolicy: { deny: [], warn: [] },
238
255
  enablePatterns: false,
239
256
  patternLibraryPath: void 0,
@@ -246,7 +263,12 @@ function createDefaultConfig(_projectRoot) {
246
263
  enableBranch: false,
247
264
  enableAgentUtils: true,
248
265
  enableGeneralCompression: false,
249
- enableShellExec: false
266
+ enableShellExec: false,
267
+ jevApiKey: void 0,
268
+ jevBaseUrl: void 0,
269
+ jevModel: "jev-latest",
270
+ strandsBaseUrl: void 0,
271
+ strandsModel: "StrandsAgents/strands-decider-2B-hobson-v19"
250
272
  };
251
273
  }
252
274
  function validateConfig(config) {
@@ -306,6 +328,9 @@ function validateConfig(config) {
306
328
  const memoryContextThreshold = typeof raw.memoryContextThreshold === "number" && raw.memoryContextThreshold >= 0 && raw.memoryContextThreshold <= 1 ? raw.memoryContextThreshold : defaults.memoryContextThreshold;
307
329
  const memoryExcludePatterns = Array.isArray(raw.memoryExcludePatterns) && raw.memoryExcludePatterns.every((p) => typeof p === "string") ? raw.memoryExcludePatterns : defaults.memoryExcludePatterns;
308
330
  const memoryStrictWrites = typeof raw.memoryStrictWrites === "boolean" ? raw.memoryStrictWrites : defaults.memoryStrictWrites;
331
+ const MEMORY_RELATION_MODES = /* @__PURE__ */ new Set(["agent", "jev", "strands"]);
332
+ const memoryRelationMode = typeof raw.memoryRelationMode === "string" && MEMORY_RELATION_MODES.has(raw.memoryRelationMode) ? raw.memoryRelationMode : defaults.memoryRelationMode;
333
+ const memoryRelationConfidenceThreshold = typeof raw.memoryRelationConfidenceThreshold === "number" && raw.memoryRelationConfidenceThreshold >= 0 && raw.memoryRelationConfidenceThreshold <= 1 ? raw.memoryRelationConfidenceThreshold : defaults.memoryRelationConfidenceThreshold;
309
334
  const memorySchemaValidation = typeof raw.memorySchemaValidation === "boolean" ? raw.memorySchemaValidation : defaults.memorySchemaValidation;
310
335
  const enableWatchmen = typeof raw.enableWatchmen === "boolean" ? raw.enableWatchmen : defaults.enableWatchmen;
311
336
  const watchmenThreshold = typeof raw.watchmenThreshold === "number" && raw.watchmenThreshold > 0 ? Math.round(raw.watchmenThreshold) : defaults.watchmenThreshold;
@@ -321,6 +346,9 @@ function validateConfig(config) {
321
346
  const wikiLintFrequency = raw.wikiLintFrequency === "weekly" ? "weekly" : "off";
322
347
  const wikiContextLimit = typeof raw.wikiContextLimit === "number" ? raw.wikiContextLimit : defaults.wikiContextLimit;
323
348
  const wikiContextThreshold = typeof raw.wikiContextThreshold === "number" ? raw.wikiContextThreshold : defaults.wikiContextThreshold;
349
+ const WIKI_CONTRADICTION_MODES = /* @__PURE__ */ new Set(["heuristic", "jev", "strands"]);
350
+ const wikiContradictionMode = typeof raw.wikiContradictionMode === "string" && WIKI_CONTRADICTION_MODES.has(raw.wikiContradictionMode) ? raw.wikiContradictionMode : "heuristic";
351
+ const wikiContradictionConfidenceThreshold = typeof raw.wikiContradictionConfidenceThreshold === "number" && raw.wikiContradictionConfidenceThreshold >= 0 && raw.wikiContradictionConfidenceThreshold <= 1 ? raw.wikiContradictionConfidenceThreshold : defaults.wikiContradictionConfidenceThreshold;
324
352
  const enableDocs = typeof raw.enableDocs === "boolean" ? raw.enableDocs : defaults.enableDocs;
325
353
  const docsInclude = Array.isArray(raw.docsInclude) && raw.docsInclude.every((p) => typeof p === "string") ? raw.docsInclude : defaults.docsInclude;
326
354
  const docsExclude = Array.isArray(raw.docsExclude) && raw.docsExclude.every((p) => typeof p === "string") ? raw.docsExclude : defaults.docsExclude;
@@ -366,6 +394,9 @@ function validateConfig(config) {
366
394
  }
367
395
  securityEnrichMaxAgeDays = defaults.securityEnrichMaxAgeDays;
368
396
  }
397
+ const SECURITY_AUTH_DETECTION_MODES = /* @__PURE__ */ new Set(["heuristic", "jev", "strands"]);
398
+ const securityAuthDetectionMode = typeof raw.securityAuthDetectionMode === "string" && SECURITY_AUTH_DETECTION_MODES.has(raw.securityAuthDetectionMode) ? raw.securityAuthDetectionMode : "heuristic";
399
+ const securityAuthConfidenceThreshold = typeof raw.securityAuthConfidenceThreshold === "number" && raw.securityAuthConfidenceThreshold >= 0 && raw.securityAuthConfidenceThreshold <= 1 ? raw.securityAuthConfidenceThreshold : defaults.securityAuthConfidenceThreshold;
369
400
  const SUPPORTED_SECURITY_DATABASES = /* @__PURE__ */ new Set(["OSV"]);
370
401
  let securityDatabases;
371
402
  if (Array.isArray(raw.securityDatabases) && raw.securityDatabases.every((d) => typeof d === "string")) {
@@ -436,6 +467,11 @@ function validateConfig(config) {
436
467
  (0, import_errors.logWarn)("enableSecurity requires enableArchitecture \u2014 auto-enabling architecture analysis");
437
468
  finalEnableArchitecture = true;
438
469
  }
470
+ const jevApiKey = typeof raw.jevApiKey === "string" && raw.jevApiKey.length > 0 ? raw.jevApiKey : void 0;
471
+ const jevBaseUrl = typeof raw.jevBaseUrl === "string" && raw.jevBaseUrl.length > 0 ? raw.jevBaseUrl : void 0;
472
+ const jevModel = typeof raw.jevModel === "string" && raw.jevModel.length > 0 ? raw.jevModel : defaults.jevModel;
473
+ const strandsBaseUrl = typeof raw.strandsBaseUrl === "string" && raw.strandsBaseUrl.length > 0 ? raw.strandsBaseUrl : void 0;
474
+ const strandsModel = typeof raw.strandsModel === "string" && raw.strandsModel.length > 0 ? raw.strandsModel : defaults.strandsModel;
439
475
  let contextBudget;
440
476
  if (raw.contextBudget && typeof raw.contextBudget === "object" && !Array.isArray(raw.contextBudget)) {
441
477
  const cb = raw.contextBudget;
@@ -482,6 +518,8 @@ function validateConfig(config) {
482
518
  memoryContextThreshold,
483
519
  memoryExcludePatterns,
484
520
  memoryStrictWrites,
521
+ memoryRelationMode,
522
+ memoryRelationConfidenceThreshold,
485
523
  memorySchemaValidation,
486
524
  enableWatchmen: enableWatchmen && enableMemory,
487
525
  watchmenThreshold,
@@ -496,6 +534,8 @@ function validateConfig(config) {
496
534
  wikiLintFrequency,
497
535
  wikiContextLimit,
498
536
  wikiContextThreshold,
537
+ wikiContradictionMode,
538
+ wikiContradictionConfidenceThreshold,
499
539
  enableDocs,
500
540
  docsInclude,
501
541
  docsExclude,
@@ -517,6 +557,8 @@ function validateConfig(config) {
517
557
  securityDatabases,
518
558
  securityAutoEnrich,
519
559
  securityEnrichMaxAgeDays,
560
+ securityAuthDetectionMode,
561
+ securityAuthConfidenceThreshold,
520
562
  securityLicensePolicy,
521
563
  enablePatterns,
522
564
  patternLibraryPath,
@@ -530,8 +572,13 @@ function validateConfig(config) {
530
572
  enableAgentUtils,
531
573
  enableGeneralCompression,
532
574
  enableShellExec: shellCompressionLevel !== "off",
575
+ jevModel,
576
+ strandsModel,
533
577
  ...architectureLayers !== void 0 ? { architectureLayers } : {},
534
- ...contextBudget !== void 0 ? { contextBudget } : {}
578
+ ...contextBudget !== void 0 ? { contextBudget } : {},
579
+ ...jevApiKey !== void 0 ? { jevApiKey } : {},
580
+ ...jevBaseUrl !== void 0 ? { jevBaseUrl } : {},
581
+ ...strandsBaseUrl !== void 0 ? { strandsBaseUrl } : {}
535
582
  };
536
583
  }
537
584
  function _validateArchitectureLayers(raw) {
@@ -569,9 +616,33 @@ const SHALLOW_TO_RECURSIVE = {
569
616
  function migrateExcludePatterns(patterns) {
570
617
  return patterns.map((p) => SHALLOW_TO_RECURSIVE[p] ?? p);
571
618
  }
619
+ function loadDotEnv(kirographDir) {
620
+ let content;
621
+ try {
622
+ content = fs.readFileSync(path.join(kirographDir, ".env"), "utf8");
623
+ } catch {
624
+ return;
625
+ }
626
+ for (const rawLine of content.split("\n")) {
627
+ const line = rawLine.trim();
628
+ if (!line || line.startsWith("#")) continue;
629
+ const eq = line.indexOf("=");
630
+ if (eq === -1) continue;
631
+ const key = line.slice(0, eq).trim();
632
+ if (!key) continue;
633
+ let value = line.slice(eq + 1).trim();
634
+ if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
635
+ value = value.slice(1, -1);
636
+ }
637
+ if (process.env[key] === void 0) {
638
+ process.env[key] = value;
639
+ }
640
+ }
641
+ }
572
642
  async function loadConfig(projectRoot) {
573
643
  const dir = path.join(projectRoot, KIROGRAPH_DIR);
574
644
  const cfgPath = path.join(dir, CONFIG_FILE);
645
+ loadDotEnv(dir);
575
646
  if (!fs.existsSync(cfgPath)) {
576
647
  const defaults = createDefaultConfig(projectRoot);
577
648
  await fs.promises.mkdir(dir, { recursive: true });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/config.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph Config System\n *\n * Mirrors CodeGraph src/config.ts \u2014 load, save, validate, and provide defaults\n * for KiroGraph configuration.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport picomatch from 'picomatch';\nimport { logWarn, logError } from './errors';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface KiroGraphConfig {\n version: number;\n languages: string[];\n include: string[];\n exclude: string[];\n maxFileSize: number;\n extractDocstrings: boolean;\n trackCallSites: boolean;\n // Parity fields:\n enableEmbeddings: boolean;\n embeddingModel: string;\n embeddingDim: number;\n /** @deprecated Use semanticEngine instead. Kept for backwards compatibility. */\n useVecIndex: boolean;\n semanticEngine: 'cosine' | 'turboquant' | 'turbovec' | 'sqlite-vec' | 'orama' | 'pglite' | 'lancedb' | 'qdrant' | 'typesense';\n /** Apply TurboQuant ANN index to memory observations and doc sections. Default: false. */\n turboquantMemDocs: boolean;\n /** TurboQuant bits per coordinate (1\u20138). Controls compression/quality tradeoff. Default: 3 (\u224825\u00D7). */\n turboquantBits: number;\n /** Apply TurboVec ANN index to memory observations and doc sections. Default: false. */\n turbovecMemDocs: boolean;\n /** TurboVec bits per coordinate (2, 3, or 4). Controls compression/quality tradeoff. Default: 4. */\n turbovecBits: number;\n typesenseDashboard: boolean;\n qdrantDashboard: boolean;\n minLogLevel: 'debug' | 'info' | 'warn' | 'error';\n frameworkHints: string[];\n fuzzyResolutionThreshold: number; // 0.0\u20131.0\n /** Enable architecture analysis (package graph + layer detection). Default: false. */\n enableArchitecture: boolean;\n /**\n * User-defined layer \u2192 glob pattern overrides.\n * When set, config-defined layers win over auto-detected ones.\n * Example: { \"api\": [\"src/routes/**\", \"src/controllers/**\"] }\n */\n architectureLayers?: Record<string, string[]>;\n /** Agent communication style injected at agentSpawn. Default: 'off'. */\n cavemanMode: 'off' | 'lite' | 'full' | 'ultra';\n /** Shell compression level for kirograph_exec. 'off' disables the hook/steering. Default: 'normal'. */\n shellCompressionLevel: 'off' | 'normal' | 'aggressive' | 'ultra';\n /**\n * Number of pending (unindexed) files above which kirograph_status warns the agent.\n * Set to 0 to disable the warning. Default: 10.\n */\n syncWarningThreshold: number;\n /** Enable persistent cross-session memory. Default: false. */\n enableMemory: boolean;\n /** FTS/vector blend for memory search: 0 = FTS only, 1 = vector only. Default: 0.5. */\n memorySearchAlpha: number;\n /** Store uncompressed originals when caveman is on. Default: false. */\n memoryKeepRaw: boolean;\n /** Auto-prune threshold (max observations). 0 = no limit. Default: 10000. */\n memoryMaxObservations: number;\n /** Seconds of inactivity before auto-closing a session. Default: 7200. */\n memorySessionTimeout: number;\n /** Max observations shown in kirograph_context. Default: 3. */\n memoryContextLimit: number;\n /** Min relevance score to include memory in context. Default: 0.3. */\n memoryContextThreshold: number;\n /** Glob patterns for paths to never capture in memory. Default: []. */\n memoryExcludePatterns: string[];\n /**\n * Reject observation writes that don't conform to the memory schema\n * (unknown `kind`, blank tags) instead of silently accepting them.\n * Applies to `kirograph mem store`, the `kirograph_mem_store` MCP tool,\n * and `MemoryManager.store()` directly. Off by default \u2014 existing\n * free-form writes are unaffected until explicitly opted in.\n * Default: false.\n */\n memoryStrictWrites: boolean;\n /**\n * Validate an observation's `fields` (structured data beyond `content`)\n * against a JSON Schema registered per kind at\n * `.kirograph/memory-schemas/<kind>.schema.json`. A kind with no schema\n * file registered is never validated \u2014 schemas are opt-in per kind.\n * Off by default; independent of memoryStrictWrites (that one validates\n * `kind`/`tags`, this one validates `fields`). Default: false.\n */\n memorySchemaValidation: boolean;\n /** Enable watchmen \u2014 auto-synthesize workspace briefs from memory observations. Requires enableMemory. Default: false. */\n enableWatchmen: boolean;\n /** Minimum new observations since last synthesis before watchmenReady fires. Default: 5. */\n watchmenThreshold: number;\n /**\n * How synthesis is performed.\n * 'local' \u2014 runs a local HuggingFace model via @huggingface/transformers (no API cost, works for all tools).\n * 'agent' \u2014 delegates to the active AI agent via askAgent hook (Kiro only, consumes agent tokens).\n * Default: 'local'.\n */\n watchmenSynthesisMode: 'local' | 'agent';\n /** HuggingFace model ID for local synthesis. Only used when watchmenSynthesisMode is 'local'. Default: 'onnx-community/gemma-4-E4B-it-ONNX'. */\n watchmenLocalModel: string;\n /** Enable documentation indexing and navigation. Default: false. */\n enableDocs: boolean;\n /** Glob patterns for documentation files to include. */\n docsInclude: string[];\n /** Glob patterns for documentation files to exclude. */\n docsExclude: string[];\n /** Enable auto-linking of doc sections to code symbols. Default: true. */\n docsLinkCode: boolean;\n /** Max doc sections to include in kirograph_context. 0 = disabled. Default: 0. */\n docsContextLimit: number;\n /** Min relevance score to include a doc section in context. Default: 0.3. */\n docsContextThreshold: number;\n /** Max file size for doc files (bytes). Default: 1MB. */\n docsMaxFileSize: number;\n /** Summarization strategy. Default: 'first-sentence'. */\n docsSummarization: 'embedding' | 'first-sentence' | 'off';\n /** Enable LLM-maintained wiki (entity pages in .kirograph/wiki/). Default: false. */\n enableWiki: boolean;\n /** Wiki synthesis mode. Default: 'agent'. */\n wikiSynthesisMode: 'agent' | 'local';\n /** HuggingFace model for local wiki synthesis. */\n wikiLocalModel: string;\n /** Glob patterns for auto-ingest wiki sources. Default: ['docs/']. */\n wikiSources: string[];\n /**\n * Validate a page's optional YAML frontmatter against a JSON Schema\n * registered per `_type` at `.kirograph/wiki-schemas/<type>.schema.json`.\n * Pages without frontmatter, or with a `_type` that has no schema\n * registered, are never validated \u2014 untyped prose pages are unaffected.\n * Checked by `wiki lint`, reported as `schema_error` issues. Default: false.\n */\n wikiTypedPages: boolean;\n /** Auto-resolve wiki conflicts by source date. Default: false. */\n wikiAutoResolveConflicts: boolean;\n /** Lint frequency: 'weekly' (every ~20 sessions) or 'off'. Default: 'off'. */\n wikiLintFrequency: 'weekly' | 'off';\n /** Max wiki pages to include in kirograph_context. Default: 3. */\n wikiContextLimit: number;\n /** Min FTS score to include wiki page in context. Default: 0.4. */\n wikiContextThreshold: number;\n /** Enable tabular data indexing and querying. Default: false. */\n enableData: boolean;\n /** Glob patterns for data files to include. */\n dataInclude: string[];\n /** Glob patterns for data files to exclude. */\n dataExclude: string[];\n /** Enable auto-linking of data files to code symbols. Default: true. */\n dataLinkCode: boolean;\n /** Max datasets to include in kirograph_context. 0 = disabled. Default: 0. */\n dataContextLimit: number;\n /** Max file size for data files (bytes). Default: 50MB. */\n dataMaxFileSize: number;\n /** Max rows to index per file. Default: 1,000,000. */\n dataMaxRows: number;\n /** Max rows returned per query. Default: 500. */\n dataQueryLimit: number;\n /** Max token budget per response. Default: 8000. */\n dataMaxResponseTokens: number;\n /** Enable security analysis (dependency scanning + vulnerability detection). Default: false. */\n enableSecurity: boolean;\n /** Vulnerability databases to query. Default: ['OSV']. */\n securityDatabases: string[];\n /** Enable AST-level structural pattern matching (SAST) during indexing. Default: false. */\n enablePatterns: boolean;\n /** Enable code health tools (hotspots, dead code, path analysis, type hierarchy). Default: false. */\n enableCodeHealth: boolean;\n /** Enable navigation tools (status, files, impact). Default: false. */\n enableNavigation: boolean;\n /** Enable complexity metrics tools. Default: false. */\n enableComplexity: boolean;\n /** Enable git-context tools (diff_context, commit_context, flows, etc.). Default: false. */\n enableGitContext: boolean;\n /** Enable atomic edit primitive tools (str_replace, insert_at, etc.) and refactor. Default: false. */\n enableEditPrimitives: boolean;\n /** Enable multi-branch graph indexing tools. Default: false. */\n enableBranch: boolean;\n /** @deprecated Dissolved \u2014 tools moved to enableCodeHealth, enableGitContext, enableArchitecture, enableEditPrimitives. Kept in KNOWN_FIELDS for silent backwards compatibility. */\n enableAdvancedAnalysis?: boolean;\n /** Enable agent utility tools (file caching, budget tracking). Default: true. */\n enableAgentUtils: boolean;\n /** Enable general-purpose compression tool (kirograph_compress). Default: false. */\n enableGeneralCompression: boolean;\n /** Derived from shellCompressionLevel \u2014 true when compression is enabled. Controls kirograph_exec. */\n enableShellExec: boolean;\n /** Path to a directory of user-supplied YAML rule files. Merged with bundled library (user rules win on id conflict). Default: undefined. */\n patternLibraryPath: string | undefined;\n /** Minimum severity level for storing pattern matches during index-time analysis. Default: 'low'. */\n patternSeverityThreshold: 'critical' | 'high' | 'medium' | 'low';\n /** Auto-run vulnerability enrichment after manifest parsing. Default: true. */\n securityAutoEnrich: boolean;\n /** Max age in days for vulnerability data before showing a staleness warning. Default: 7. */\n securityEnrichMaxAgeDays: number;\n /**\n * License policy for dependency compliance.\n * deny: licenses to block (build fails / command exits non-zero).\n * warn: licenses to flag as warnings.\n * Patterns support wildcards: GPL-* matches GPL-2.0, GPL-3.0, etc.\n * Default: { deny: [], warn: [] }.\n */\n securityLicensePolicy: {\n deny: string[];\n warn: string[];\n };\n /** Context budget governance settings. */\n contextBudget?: {\n maxTokensPerSession: number;\n warnAt: number;\n throttleAt: number;\n };\n}\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst KIROGRAPH_DIR = '.kirograph';\nconst CONFIG_FILE = 'config.json';\n\nconst KNOWN_FIELDS = new Set<string>([\n 'version', 'languages', 'include', 'exclude', 'maxFileSize',\n 'extractDocstrings', 'trackCallSites', 'enableEmbeddings', 'embeddingModel', 'embeddingDim',\n 'useVecIndex', 'semanticEngine', 'turboquantMemDocs', 'turboquantBits', 'turbovecMemDocs', 'turbovecBits', 'typesenseDashboard', 'qdrantDashboard',\n 'minLogLevel', 'frameworkHints', 'fuzzyResolutionThreshold',\n 'enableArchitecture', 'architectureLayers', 'cavemanMode', 'shellCompressionLevel', 'syncWarningThreshold',\n 'enableMemory', 'memorySearchAlpha', 'memoryKeepRaw', 'memoryMaxObservations',\n 'memorySessionTimeout', 'memoryContextLimit', 'memoryContextThreshold', 'memoryExcludePatterns', 'memoryStrictWrites',\n 'memorySchemaValidation',\n 'enableWatchmen', 'watchmenThreshold', 'watchmenSynthesisMode', 'watchmenLocalModel',\n 'enableWiki', 'wikiSynthesisMode', 'wikiLocalModel', 'wikiSources', 'wikiTypedPages',\n 'wikiAutoResolveConflicts', 'wikiLintFrequency', 'wikiContextLimit', 'wikiContextThreshold',\n 'enableDocs', 'docsInclude', 'docsExclude', 'docsLinkCode',\n 'docsContextLimit', 'docsContextThreshold', 'docsMaxFileSize', 'docsSummarization',\n 'enableData', 'dataInclude', 'dataExclude', 'dataLinkCode',\n 'dataContextLimit', 'dataMaxFileSize', 'dataMaxRows', 'dataQueryLimit', 'dataMaxResponseTokens',\n 'enableSecurity', 'securityDatabases', 'securityAutoEnrich', 'securityEnrichMaxAgeDays', 'securityLicensePolicy',\n 'enablePatterns', 'patternLibraryPath', 'patternSeverityThreshold',\n 'enableCodeHealth', 'enableNavigation', 'enableComplexity', 'enableGitContext',\n 'enableEditPrimitives', 'enableBranch',\n 'enableAgentUtils', 'enableGeneralCompression',\n 'contextBudget',\n // Legacy aliases / derived fields (accepted but ignored or recomputed)\n 'enableCompression', 'compressionLevel', 'enableShellExec',\n // Deprecated: dissolved flag kept here so old configs don't warn\n 'enableAdvancedAnalysis',\n]);\n\nconst LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error']);\n\n// \u2500\u2500 ReDoS-safe regex check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Returns false if the pattern is potentially dangerous (ReDoS risk) or too long.\n * Checks for catastrophic backtracking patterns like (a+)+ or (a|a)+.\n */\nexport function isSafeRegex(pattern: string): boolean {\n if (pattern.length > 100) return false;\n // Detect nested quantifiers: (x+)+ or (x*)+ or (x+)* etc.\n if (/\\([^)]*[+*][^)]*\\)[+*?]/.test(pattern)) return false;\n // Detect alternation with overlap: (a|a)+ style\n if (/\\([^)]*\\|[^)]*\\)[+*]/.test(pattern)) return false;\n return true;\n}\n\n// \u2500\u2500 Default config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function createDefaultConfig(_projectRoot?: string): KiroGraphConfig {\n return {\n version: 2,\n languages: [],\n include: [],\n exclude: [\n '**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.kirograph/**',\n // Compiled / minified output and build artifacts \u2014 not meaningful source to index,\n // and large bundles can crash the parser (issue #33). '*.min.js' was previously\n // non-recursive (root-only); use '**/' so nested bundles are matched.\n '**/*.min.js', '**/*.min.css', '**/*.bundle.js', '**/*.map',\n '**/out/**', '**/.next/**', '**/.nuxt/**', '**/.vite/**', '**/.svelte-kit/**',\n '**/public/build/**', '**/Resources/Public/**',\n ],\n maxFileSize: 1_048_576,\n extractDocstrings: false,\n trackCallSites: false,\n enableEmbeddings: false,\n embeddingModel: 'nomic-ai/nomic-embed-text-v1.5',\n embeddingDim: 768,\n useVecIndex: false,\n semanticEngine: 'cosine',\n turboquantMemDocs: false,\n turboquantBits: 3,\n turbovecMemDocs: false,\n turbovecBits: 4,\n typesenseDashboard: false,\n qdrantDashboard: false,\n minLogLevel: 'warn',\n frameworkHints: [],\n fuzzyResolutionThreshold: 0.5,\n enableArchitecture: false,\n cavemanMode: 'off',\n shellCompressionLevel: 'off',\n syncWarningThreshold: 10,\n enableMemory: false,\n memorySearchAlpha: 0.5,\n memoryKeepRaw: false,\n memoryMaxObservations: 10000,\n memorySessionTimeout: 7200,\n memoryContextLimit: 3,\n memoryContextThreshold: 0.3,\n memoryExcludePatterns: [],\n memoryStrictWrites: false,\n memorySchemaValidation: false,\n enableWatchmen: false,\n watchmenThreshold: 5,\n watchmenSynthesisMode: 'local',\n watchmenLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n enableWiki: false,\n wikiSynthesisMode: 'agent' as const,\n wikiLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n wikiSources: ['docs/'],\n wikiTypedPages: false,\n wikiAutoResolveConflicts: false,\n wikiLintFrequency: 'off' as const,\n wikiContextLimit: 3,\n wikiContextThreshold: 0.4,\n enableDocs: false,\n docsInclude: ['**/*.md', '**/*.mdx', '**/*.rst', '**/*.adoc', '**/*.asciidoc', '**/*.rdoc', '**/*.org', '**/*.cheatmd', 'docs/**/*.txt', 'docs/**/*.html'],\n docsExclude: ['node_modules/**', '**/CHANGELOG*', '**/LICENSE*', '**/CHANGES*', 'dist/**', 'build/**', 'coverage/**', '.git/**', '**/generated/**', '**/auto-generated/**', '**/vendor/**', '_build/**'],\n docsLinkCode: true,\n docsContextLimit: 0,\n docsContextThreshold: 0.3,\n docsMaxFileSize: 1_048_576,\n docsSummarization: 'first-sentence',\n enableData: false,\n dataInclude: ['**/*.csv', '**/*.tsv', '**/*.jsonl', '**/*.ndjson', '**/*.xlsx', '**/*.xls', '**/*.parquet', 'data/**/*.json', '**/*.pdf'],\n dataExclude: ['node_modules/**', 'dist/**', 'build/**', '.git/**', '**/package-lock.json', '**/yarn.lock', '**/pnpm-lock.yaml', '**/tsconfig.json', '**/jsconfig.json', 'coverage/**', '**/generated/**'],\n dataLinkCode: true,\n dataContextLimit: 0,\n dataMaxFileSize: 52_428_800,\n dataMaxRows: 1_000_000,\n dataQueryLimit: 500,\n dataMaxResponseTokens: 8000,\n enableSecurity: false,\n securityDatabases: ['OSV'],\n securityAutoEnrich: true,\n securityEnrichMaxAgeDays: 7,\n securityLicensePolicy: { deny: [], warn: [] },\n enablePatterns: false,\n patternLibraryPath: undefined,\n patternSeverityThreshold: 'low',\n enableCodeHealth: false,\n enableNavigation: false,\n enableComplexity: false,\n enableGitContext: false,\n enableEditPrimitives: false,\n enableBranch: false,\n enableAgentUtils: true,\n enableGeneralCompression: false,\n enableShellExec: false,\n };\n}\n\n// \u2500\u2500 Validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function validateConfig(config: unknown): KiroGraphConfig {\n const defaults = createDefaultConfig();\n\n if (typeof config !== 'object' || config === null) {\n return defaults;\n }\n\n const raw = config as Record<string, unknown>;\n\n // Warn about unknown fields\n for (const key of Object.keys(raw)) {\n if (!KNOWN_FIELDS.has(key)) {\n logWarn(`Unknown config field: ${key}`);\n }\n }\n\n // Validate and coerce each field\n const version = typeof raw.version === 'number' ? raw.version : defaults.version;\n const languages = Array.isArray(raw.languages) && raw.languages.every(l => typeof l === 'string')\n ? (raw.languages as string[])\n : defaults.languages;\n const maxFileSize = typeof raw.maxFileSize === 'number' && raw.maxFileSize > 0\n ? raw.maxFileSize\n : defaults.maxFileSize;\n const extractDocstrings = typeof raw.extractDocstrings === 'boolean'\n ? raw.extractDocstrings\n : defaults.extractDocstrings;\n const trackCallSites = typeof raw.trackCallSites === 'boolean'\n ? raw.trackCallSites\n : defaults.trackCallSites;\n const enableEmbeddings = typeof raw.enableEmbeddings === 'boolean'\n ? raw.enableEmbeddings\n : defaults.enableEmbeddings;\n const embeddingModel = typeof raw.embeddingModel === 'string' && raw.embeddingModel.length > 0\n ? raw.embeddingModel\n : defaults.embeddingModel;\n const embeddingDim = typeof raw.embeddingDim === 'number' && raw.embeddingDim > 0\n ? raw.embeddingDim\n : defaults.embeddingDim;\n const useVecIndex = typeof raw.useVecIndex === 'boolean'\n ? raw.useVecIndex\n : defaults.useVecIndex;\n const SEMANTIC_ENGINES = new Set(['cosine', 'turboquant', 'turbovec', 'sqlite-vec', 'orama', 'pglite', 'lancedb', 'qdrant', 'typesense']);\n // useVecIndex is a legacy alias: if set and no explicit semanticEngine, map it\n const semanticEngine = typeof raw.semanticEngine === 'string' && SEMANTIC_ENGINES.has(raw.semanticEngine)\n ? (raw.semanticEngine as KiroGraphConfig['semanticEngine'])\n : useVecIndex ? 'sqlite-vec' : defaults.semanticEngine;\n const turboquantMemDocs = typeof raw.turboquantMemDocs === 'boolean'\n ? raw.turboquantMemDocs\n : defaults.turboquantMemDocs;\n const turboquantBits = typeof raw.turboquantBits === 'number'\n && raw.turboquantBits >= 1 && raw.turboquantBits <= 8\n ? Math.round(raw.turboquantBits)\n : defaults.turboquantBits;\n const turbovecMemDocs = typeof raw.turbovecMemDocs === 'boolean'\n ? raw.turbovecMemDocs\n : defaults.turbovecMemDocs;\n const TURBOVEC_BIT_WIDTHS = new Set([2, 3, 4]);\n const turbovecBits = typeof raw.turbovecBits === 'number' && TURBOVEC_BIT_WIDTHS.has(Math.round(raw.turbovecBits))\n ? Math.round(raw.turbovecBits)\n : defaults.turbovecBits;\n const typesenseDashboard = typeof raw.typesenseDashboard === 'boolean'\n ? raw.typesenseDashboard\n : defaults.typesenseDashboard;\n const qdrantDashboard = typeof raw.qdrantDashboard === 'boolean'\n ? raw.qdrantDashboard\n : defaults.qdrantDashboard;\n const minLogLevel = typeof raw.minLogLevel === 'string' && LOG_LEVELS.has(raw.minLogLevel)\n ? (raw.minLogLevel as KiroGraphConfig['minLogLevel'])\n : defaults.minLogLevel;\n const frameworkHints = Array.isArray(raw.frameworkHints) && raw.frameworkHints.every(h => typeof h === 'string')\n ? (raw.frameworkHints as string[])\n : defaults.frameworkHints;\n const fuzzyResolutionThreshold = typeof raw.fuzzyResolutionThreshold === 'number'\n && raw.fuzzyResolutionThreshold >= 0\n && raw.fuzzyResolutionThreshold <= 1\n ? raw.fuzzyResolutionThreshold\n : defaults.fuzzyResolutionThreshold;\n const enableArchitecture = typeof raw.enableArchitecture === 'boolean'\n ? raw.enableArchitecture\n : defaults.enableArchitecture;\n const architectureLayers = _validateArchitectureLayers(raw.architectureLayers);\n const CAVEMAN_MODES = new Set(['off', 'lite', 'full', 'ultra']);\n const cavemanMode = typeof raw.cavemanMode === 'string' && CAVEMAN_MODES.has(raw.cavemanMode)\n ? (raw.cavemanMode as KiroGraphConfig['cavemanMode'])\n : defaults.cavemanMode;\n const COMPRESSION_LEVELS = new Set(['off', 'normal', 'aggressive', 'ultra']);\n // Support legacy field names: enableCompression (boolean) and compressionLevel (string)\n let shellCompressionLevel: KiroGraphConfig['shellCompressionLevel'];\n if (typeof raw.shellCompressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.shellCompressionLevel)) {\n shellCompressionLevel = raw.shellCompressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.compressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.compressionLevel)) {\n shellCompressionLevel = raw.compressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.enableCompression === 'boolean') {\n shellCompressionLevel = raw.enableCompression ? 'normal' : 'off';\n } else {\n shellCompressionLevel = defaults.shellCompressionLevel;\n }\n const syncWarningThreshold = typeof raw.syncWarningThreshold === 'number' && raw.syncWarningThreshold >= 0\n ? Math.round(raw.syncWarningThreshold)\n : defaults.syncWarningThreshold;\n\n // \u2500\u2500 Memory config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableMemory = typeof raw.enableMemory === 'boolean'\n ? raw.enableMemory\n : defaults.enableMemory;\n const memorySearchAlpha = typeof raw.memorySearchAlpha === 'number'\n && raw.memorySearchAlpha >= 0 && raw.memorySearchAlpha <= 1\n ? raw.memorySearchAlpha\n : defaults.memorySearchAlpha;\n const memoryKeepRaw = typeof raw.memoryKeepRaw === 'boolean'\n ? raw.memoryKeepRaw\n : defaults.memoryKeepRaw;\n const memoryMaxObservations = typeof raw.memoryMaxObservations === 'number' && raw.memoryMaxObservations >= 0\n ? Math.round(raw.memoryMaxObservations)\n : defaults.memoryMaxObservations;\n const memorySessionTimeout = typeof raw.memorySessionTimeout === 'number' && raw.memorySessionTimeout > 0\n ? Math.round(raw.memorySessionTimeout)\n : defaults.memorySessionTimeout;\n const memoryContextLimit = typeof raw.memoryContextLimit === 'number' && raw.memoryContextLimit >= 0\n ? Math.round(raw.memoryContextLimit)\n : defaults.memoryContextLimit;\n const memoryContextThreshold = typeof raw.memoryContextThreshold === 'number'\n && raw.memoryContextThreshold >= 0 && raw.memoryContextThreshold <= 1\n ? raw.memoryContextThreshold\n : defaults.memoryContextThreshold;\n const memoryExcludePatterns = Array.isArray(raw.memoryExcludePatterns)\n && raw.memoryExcludePatterns.every((p: unknown) => typeof p === 'string')\n ? (raw.memoryExcludePatterns as string[])\n : defaults.memoryExcludePatterns;\n const memoryStrictWrites = typeof raw.memoryStrictWrites === 'boolean'\n ? raw.memoryStrictWrites\n : defaults.memoryStrictWrites;\n const memorySchemaValidation = typeof raw.memorySchemaValidation === 'boolean'\n ? raw.memorySchemaValidation\n : defaults.memorySchemaValidation;\n\n // \u2500\u2500 Watchmen config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableWatchmen = typeof raw.enableWatchmen === 'boolean'\n ? raw.enableWatchmen\n : defaults.enableWatchmen;\n const watchmenThreshold = typeof raw.watchmenThreshold === 'number' && raw.watchmenThreshold > 0\n ? Math.round(raw.watchmenThreshold)\n : defaults.watchmenThreshold;\n const WATCHMEN_SYNTHESIS_MODES = new Set(['local', 'agent']);\n const watchmenSynthesisMode = typeof raw.watchmenSynthesisMode === 'string' && WATCHMEN_SYNTHESIS_MODES.has(raw.watchmenSynthesisMode)\n ? (raw.watchmenSynthesisMode as KiroGraphConfig['watchmenSynthesisMode'])\n : defaults.watchmenSynthesisMode;\n const watchmenLocalModel = typeof raw.watchmenLocalModel === 'string' && raw.watchmenLocalModel.length > 0\n ? raw.watchmenLocalModel\n : defaults.watchmenLocalModel;\n\n // \u2500\u2500 Wiki config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableWiki = typeof raw.enableWiki === 'boolean' ? raw.enableWiki : defaults.enableWiki;\n const wikiSynthesisMode = raw.wikiSynthesisMode === 'local' ? 'local' as const : 'agent' as const;\n const wikiLocalModel = typeof raw.wikiLocalModel === 'string' ? raw.wikiLocalModel : defaults.wikiLocalModel;\n const wikiSources = Array.isArray(raw.wikiSources) ? raw.wikiSources : defaults.wikiSources;\n const wikiTypedPages = typeof raw.wikiTypedPages === 'boolean' ? raw.wikiTypedPages : defaults.wikiTypedPages;\n const wikiAutoResolveConflicts = typeof raw.wikiAutoResolveConflicts === 'boolean' ? raw.wikiAutoResolveConflicts : defaults.wikiAutoResolveConflicts;\n const wikiLintFrequency = raw.wikiLintFrequency === 'weekly' ? 'weekly' as const : 'off' as const;\n const wikiContextLimit = typeof raw.wikiContextLimit === 'number' ? raw.wikiContextLimit : defaults.wikiContextLimit;\n const wikiContextThreshold = typeof raw.wikiContextThreshold === 'number' ? raw.wikiContextThreshold : defaults.wikiContextThreshold;\n\n // \u2500\u2500 Docs config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableDocs = typeof raw.enableDocs === 'boolean'\n ? raw.enableDocs\n : defaults.enableDocs;\n const docsInclude = Array.isArray(raw.docsInclude)\n && raw.docsInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsInclude as string[])\n : defaults.docsInclude;\n const docsExclude = Array.isArray(raw.docsExclude)\n && raw.docsExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsExclude as string[])\n : defaults.docsExclude;\n const docsLinkCode = typeof raw.docsLinkCode === 'boolean'\n ? raw.docsLinkCode\n : defaults.docsLinkCode;\n const docsContextLimit = typeof raw.docsContextLimit === 'number' && raw.docsContextLimit >= 0\n ? Math.round(raw.docsContextLimit)\n : defaults.docsContextLimit;\n const docsContextThreshold = typeof raw.docsContextThreshold === 'number'\n && raw.docsContextThreshold >= 0 && raw.docsContextThreshold <= 1\n ? raw.docsContextThreshold\n : defaults.docsContextThreshold;\n const docsMaxFileSize = typeof raw.docsMaxFileSize === 'number' && raw.docsMaxFileSize > 0\n ? raw.docsMaxFileSize\n : defaults.docsMaxFileSize;\n const DOCS_SUMMARIZATION_MODES = new Set(['embedding', 'first-sentence', 'off']);\n const docsSummarization = typeof raw.docsSummarization === 'string' && DOCS_SUMMARIZATION_MODES.has(raw.docsSummarization)\n ? (raw.docsSummarization as KiroGraphConfig['docsSummarization'])\n : defaults.docsSummarization;\n\n // \u2500\u2500 Data config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableData = typeof raw.enableData === 'boolean' ? raw.enableData : defaults.enableData;\n const dataInclude = Array.isArray(raw.dataInclude) && raw.dataInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataInclude as string[]) : defaults.dataInclude;\n const dataExclude = Array.isArray(raw.dataExclude) && raw.dataExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataExclude as string[]) : defaults.dataExclude;\n const dataLinkCode = typeof raw.dataLinkCode === 'boolean' ? raw.dataLinkCode : defaults.dataLinkCode;\n const dataContextLimit = typeof raw.dataContextLimit === 'number' && raw.dataContextLimit >= 0\n ? Math.round(raw.dataContextLimit) : defaults.dataContextLimit;\n const dataMaxFileSize = typeof raw.dataMaxFileSize === 'number' && raw.dataMaxFileSize > 0\n ? raw.dataMaxFileSize : defaults.dataMaxFileSize;\n const dataMaxRows = typeof raw.dataMaxRows === 'number' && raw.dataMaxRows > 0\n ? Math.round(raw.dataMaxRows) : defaults.dataMaxRows;\n const dataQueryLimit = typeof raw.dataQueryLimit === 'number' && raw.dataQueryLimit > 0\n ? Math.min(Math.round(raw.dataQueryLimit), 500) : defaults.dataQueryLimit;\n const dataMaxResponseTokens = typeof raw.dataMaxResponseTokens === 'number' && raw.dataMaxResponseTokens > 0\n ? Math.round(raw.dataMaxResponseTokens) : defaults.dataMaxResponseTokens;\n\n // \u2500\u2500 Security config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let enableSecurity: boolean;\n if (typeof raw.enableSecurity === 'boolean') {\n enableSecurity = raw.enableSecurity;\n } else {\n if (raw.enableSecurity !== undefined) {\n logWarn('Invalid config field enableSecurity: expected boolean, applying default (false)');\n }\n enableSecurity = defaults.enableSecurity;\n }\n\n let securityAutoEnrich: boolean;\n if (typeof raw.securityAutoEnrich === 'boolean') {\n securityAutoEnrich = raw.securityAutoEnrich;\n } else {\n if (raw.securityAutoEnrich !== undefined) {\n logWarn('Invalid config field securityAutoEnrich: expected boolean, applying default (true)');\n }\n securityAutoEnrich = defaults.securityAutoEnrich;\n }\n\n let securityEnrichMaxAgeDays: number;\n if (typeof raw.securityEnrichMaxAgeDays === 'number' && raw.securityEnrichMaxAgeDays > 0) {\n securityEnrichMaxAgeDays = raw.securityEnrichMaxAgeDays;\n } else {\n if (raw.securityEnrichMaxAgeDays !== undefined) {\n logWarn('Invalid config field securityEnrichMaxAgeDays: expected positive number, applying default (7)');\n }\n securityEnrichMaxAgeDays = defaults.securityEnrichMaxAgeDays;\n }\n\n const SUPPORTED_SECURITY_DATABASES = new Set(['OSV']);\n let securityDatabases: string[];\n if (Array.isArray(raw.securityDatabases) && raw.securityDatabases.every((d: unknown) => typeof d === 'string')) {\n const valid = (raw.securityDatabases as string[]).filter(d => {\n if (!SUPPORTED_SECURITY_DATABASES.has(d)) {\n logWarn(`Unsupported security database \"${d}\" in securityDatabases, ignoring`);\n return false;\n }\n return true;\n });\n securityDatabases = valid.length > 0 ? valid : defaults.securityDatabases;\n } else {\n if (raw.securityDatabases !== undefined) {\n logWarn('Invalid config field securityDatabases: expected array of strings, applying default ([\"OSV\"])');\n }\n securityDatabases = defaults.securityDatabases;\n }\n\n let securityLicensePolicy: KiroGraphConfig['securityLicensePolicy'];\n if (raw.securityLicensePolicy && typeof raw.securityLicensePolicy === 'object' && !Array.isArray(raw.securityLicensePolicy)) {\n const rawPolicy = raw.securityLicensePolicy as Record<string, unknown>;\n const deny = Array.isArray(rawPolicy.deny) && rawPolicy.deny.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.deny as string[])\n : defaults.securityLicensePolicy.deny;\n const warn = Array.isArray(rawPolicy.warn) && rawPolicy.warn.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.warn as string[])\n : defaults.securityLicensePolicy.warn;\n securityLicensePolicy = { deny, warn };\n } else {\n if (raw.securityLicensePolicy !== undefined) {\n logWarn('Invalid config field securityLicensePolicy: expected object with deny/warn arrays, applying default');\n }\n securityLicensePolicy = defaults.securityLicensePolicy;\n }\n\n // \u2500\u2500 Patterns config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let enablePatterns: boolean;\n if (typeof raw.enablePatterns === 'boolean') {\n enablePatterns = raw.enablePatterns;\n } else {\n if (raw.enablePatterns !== undefined) {\n logWarn('Invalid config field enablePatterns: expected boolean, applying default (false)');\n }\n enablePatterns = defaults.enablePatterns;\n }\n\n let patternLibraryPath: string | undefined;\n if (raw.patternLibraryPath === undefined || raw.patternLibraryPath === null) {\n patternLibraryPath = undefined;\n } else if (typeof raw.patternLibraryPath === 'string') {\n patternLibraryPath = raw.patternLibraryPath;\n } else {\n logWarn('Invalid config field patternLibraryPath: expected string or undefined, applying default (undefined)');\n patternLibraryPath = defaults.patternLibraryPath;\n }\n\n const PATTERN_SEVERITY_LEVELS = new Set(['critical', 'high', 'medium', 'low']);\n let patternSeverityThreshold: KiroGraphConfig['patternSeverityThreshold'];\n if (typeof raw.patternSeverityThreshold === 'string' && PATTERN_SEVERITY_LEVELS.has(raw.patternSeverityThreshold)) {\n patternSeverityThreshold = raw.patternSeverityThreshold as KiroGraphConfig['patternSeverityThreshold'];\n } else {\n if (raw.patternSeverityThreshold !== undefined) {\n logWarn('Invalid config field patternSeverityThreshold: expected critical|high|medium|low, applying default (low)');\n }\n patternSeverityThreshold = defaults.patternSeverityThreshold;\n }\n\n // \u2500\u2500 Tool group flags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableCodeHealth = typeof raw.enableCodeHealth === 'boolean'\n ? raw.enableCodeHealth\n : defaults.enableCodeHealth;\n const enableNavigation = typeof raw.enableNavigation === 'boolean'\n ? raw.enableNavigation\n : defaults.enableNavigation;\n const enableComplexity = typeof raw.enableComplexity === 'boolean'\n ? raw.enableComplexity\n : defaults.enableComplexity;\n const enableGitContext = typeof raw.enableGitContext === 'boolean'\n ? raw.enableGitContext\n : defaults.enableGitContext;\n const enableEditPrimitives = typeof raw.enableEditPrimitives === 'boolean'\n ? raw.enableEditPrimitives\n : defaults.enableEditPrimitives;\n const enableBranch = typeof raw.enableBranch === 'boolean'\n ? raw.enableBranch\n : defaults.enableBranch;\n // enableAdvancedAnalysis is deprecated \u2014 silently accepted, not applied\n const enableAgentUtils = typeof raw.enableAgentUtils === 'boolean'\n ? raw.enableAgentUtils\n : defaults.enableAgentUtils;\n const enableGeneralCompression = typeof raw.enableGeneralCompression === 'boolean'\n ? raw.enableGeneralCompression\n : defaults.enableGeneralCompression;\n\n // Dependency constraint: enableSecurity requires enableArchitecture\n let finalEnableArchitecture = enableArchitecture;\n if (enableSecurity && !enableArchitecture) {\n logWarn('enableSecurity requires enableArchitecture \\u2014 auto-enabling architecture analysis');\n finalEnableArchitecture = true;\n }\n\n // \u2500\u2500 Context budget config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let contextBudget: KiroGraphConfig['contextBudget'] | undefined;\n if (raw.contextBudget && typeof raw.contextBudget === 'object' && !Array.isArray(raw.contextBudget)) {\n const cb = raw.contextBudget as Record<string, unknown>;\n contextBudget = {\n maxTokensPerSession: typeof cb.maxTokensPerSession === 'number' && cb.maxTokensPerSession > 0\n ? Math.round(cb.maxTokensPerSession) : 100_000,\n warnAt: typeof cb.warnAt === 'number' && cb.warnAt > 0\n ? Math.round(cb.warnAt) : 80_000,\n throttleAt: typeof cb.throttleAt === 'number' && cb.throttleAt > 0\n ? Math.round(cb.throttleAt) : 95_000,\n };\n }\n\n // Validate glob patterns \u2014 exclude unsafe regex patterns\n const include = _validatePatterns(raw.include, defaults.include);\n const exclude = _validatePatterns(raw.exclude, defaults.exclude);\n\n return {\n version,\n languages,\n include,\n exclude,\n maxFileSize,\n extractDocstrings,\n trackCallSites,\n enableEmbeddings,\n embeddingModel,\n embeddingDim,\n useVecIndex,\n semanticEngine,\n turboquantMemDocs,\n turboquantBits,\n turbovecMemDocs,\n turbovecBits,\n typesenseDashboard,\n qdrantDashboard,\n minLogLevel,\n frameworkHints,\n fuzzyResolutionThreshold,\n enableArchitecture: finalEnableArchitecture,\n cavemanMode,\n shellCompressionLevel,\n syncWarningThreshold,\n enableMemory,\n memorySearchAlpha,\n memoryKeepRaw,\n memoryMaxObservations,\n memorySessionTimeout,\n memoryContextLimit,\n memoryContextThreshold,\n memoryExcludePatterns,\n memoryStrictWrites,\n memorySchemaValidation,\n enableWatchmen: enableWatchmen && enableMemory,\n watchmenThreshold,\n watchmenSynthesisMode,\n watchmenLocalModel,\n enableWiki,\n wikiSynthesisMode,\n wikiLocalModel,\n wikiSources,\n wikiTypedPages,\n wikiAutoResolveConflicts,\n wikiLintFrequency,\n wikiContextLimit,\n wikiContextThreshold,\n enableDocs,\n docsInclude,\n docsExclude,\n docsLinkCode,\n docsContextLimit,\n docsContextThreshold,\n docsMaxFileSize,\n docsSummarization,\n enableData,\n dataInclude,\n dataExclude,\n dataLinkCode,\n dataContextLimit,\n dataMaxFileSize,\n dataMaxRows,\n dataQueryLimit,\n dataMaxResponseTokens,\n enableSecurity,\n securityDatabases,\n securityAutoEnrich,\n securityEnrichMaxAgeDays,\n securityLicensePolicy,\n enablePatterns,\n patternLibraryPath,\n patternSeverityThreshold,\n enableCodeHealth,\n enableNavigation,\n enableComplexity,\n enableGitContext,\n enableEditPrimitives,\n enableBranch,\n enableAgentUtils,\n enableGeneralCompression,\n enableShellExec: shellCompressionLevel !== 'off',\n ...(architectureLayers !== undefined ? { architectureLayers } : {}),\n ...(contextBudget !== undefined ? { contextBudget } : {}),\n };\n}\n\nfunction _validateArchitectureLayers(raw: unknown): Record<string, string[]> | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw !== 'object' || Array.isArray(raw)) return undefined;\n const result: Record<string, string[]> = {};\n for (const [key, val] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof key !== 'string') continue;\n if (!Array.isArray(val)) continue;\n const patterns = val.filter((p): p is string => typeof p === 'string' && isSafeRegex(p));\n if (patterns.length > 0) result[key] = patterns;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction _validatePatterns(raw: unknown, fallback: string[]): string[] {\n if (!Array.isArray(raw)) return fallback;\n const valid: string[] = [];\n for (const p of raw) {\n if (typeof p !== 'string') continue;\n if (!isSafeRegex(p)) {\n logWarn(`Unsafe regex pattern skipped: ${p}`);\n continue;\n }\n valid.push(p);\n }\n return valid;\n}\n\n// \u2500\u2500 Migration helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Upgrades shallow exclude patterns (e.g. \"node_modules/**\") to recursive ones\n * (e.g. \"** /node_modules/**\") so nested directories are excluded at any depth.\n */\nconst SHALLOW_TO_RECURSIVE: Record<string, string> = {\n 'node_modules/**': '**/node_modules/**',\n 'dist/**': '**/dist/**',\n 'build/**': '**/build/**',\n '.git/**': '**/.git/**',\n '.kirograph/**': '**/.kirograph/**',\n};\n\nfunction migrateExcludePatterns(patterns: string[]): string[] {\n return patterns.map(p => SHALLOW_TO_RECURSIVE[p] ?? p);\n}\n\n// \u2500\u2500 Load / Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function loadConfig(projectRoot: string): Promise<KiroGraphConfig> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n\n if (!fs.existsSync(cfgPath)) {\n // Create default config file\n const defaults = createDefaultConfig(projectRoot);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, defaults);\n return defaults;\n }\n\n let raw: unknown;\n try {\n const text = await fs.promises.readFile(cfgPath, 'utf8');\n raw = JSON.parse(text);\n } catch (err) {\n logError('Config parse error', { path: cfgPath, error: err instanceof Error ? err.message : String(err) });\n return createDefaultConfig(projectRoot);\n }\n\n const config = validateConfig(raw);\n\n // Migrate v1 \u2192 v2: upgrade shallow exclude patterns to recursive\n if (config.version < 2) {\n config.version = 2;\n config.exclude = migrateExcludePatterns(config.exclude);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n }\n\n return config;\n}\n\nexport async function saveConfig(projectRoot: string, config: KiroGraphConfig): Promise<void> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n}\n\nasync function _writeAtomic(cfgPath: string, config: KiroGraphConfig): Promise<void> {\n const tmp = cfgPath + '.tmp';\n await fs.promises.writeFile(tmp, JSON.stringify(config, null, 2), 'utf8');\n await fs.promises.rename(tmp, cfgPath);\n}\n\n// \u2500\u2500 Update helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function updateConfig(\n projectRoot: string,\n patch: Partial<KiroGraphConfig>\n): Promise<KiroGraphConfig> {\n const current = await loadConfig(projectRoot);\n const updated = validateConfig({ ...current, ...patch });\n await saveConfig(projectRoot, updated);\n return updated;\n}\n\nexport async function addIncludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.include);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, include: [...config.include, ...toAdd] });\n}\n\nexport async function addExcludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.exclude);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, exclude: [...config.exclude, ...toAdd] });\n}\n\n// \u2500\u2500 File inclusion check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function shouldIncludeFile(config: KiroGraphConfig, relPath: string): boolean {\n // Check exclude patterns first\n for (const pattern of config.exclude) {\n if (picomatch(pattern)(relPath)) return false;\n }\n // If include patterns are specified, file must match at least one\n if (config.include.length > 0) {\n return config.include.some(pattern => picomatch(pattern)(relPath));\n }\n return true;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph Config System\n *\n * Mirrors CodeGraph src/config.ts \u2014 load, save, validate, and provide defaults\n * for KiroGraph configuration.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport picomatch from 'picomatch';\nimport { logWarn, logError } from './errors';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface KiroGraphConfig {\n version: number;\n languages: string[];\n include: string[];\n exclude: string[];\n maxFileSize: number;\n extractDocstrings: boolean;\n trackCallSites: boolean;\n // Parity fields:\n enableEmbeddings: boolean;\n embeddingModel: string;\n embeddingDim: number;\n /** @deprecated Use semanticEngine instead. Kept for backwards compatibility. */\n useVecIndex: boolean;\n semanticEngine: 'cosine' | 'turboquant' | 'turbovec' | 'sqlite-vec' | 'orama' | 'pglite' | 'lancedb' | 'qdrant' | 'typesense';\n /** Apply TurboQuant ANN index to memory observations and doc sections. Default: false. */\n turboquantMemDocs: boolean;\n /** TurboQuant bits per coordinate (1\u20138). Controls compression/quality tradeoff. Default: 3 (\u224825\u00D7). */\n turboquantBits: number;\n /** Apply TurboVec ANN index to memory observations and doc sections. Default: false. */\n turbovecMemDocs: boolean;\n /** TurboVec bits per coordinate (2, 3, or 4). Controls compression/quality tradeoff. Default: 4. */\n turbovecBits: number;\n typesenseDashboard: boolean;\n qdrantDashboard: boolean;\n minLogLevel: 'debug' | 'info' | 'warn' | 'error';\n frameworkHints: string[];\n fuzzyResolutionThreshold: number; // 0.0\u20131.0\n /** Enable architecture analysis (package graph + layer detection). Default: false. */\n enableArchitecture: boolean;\n /**\n * User-defined layer \u2192 glob pattern overrides.\n * When set, config-defined layers win over auto-detected ones.\n * Example: { \"api\": [\"src/routes/**\", \"src/controllers/**\"] }\n */\n architectureLayers?: Record<string, string[]>;\n /** Agent communication style injected at agentSpawn. Default: 'off'. */\n cavemanMode: 'off' | 'lite' | 'full' | 'ultra';\n /** Shell compression level for kirograph_exec. 'off' disables the hook/steering. Default: 'normal'. */\n shellCompressionLevel: 'off' | 'normal' | 'aggressive' | 'ultra';\n /**\n * Number of pending (unindexed) files above which kirograph_status warns the agent.\n * Set to 0 to disable the warning. Default: 10.\n */\n syncWarningThreshold: number;\n /** Enable persistent cross-session memory. Default: false. */\n enableMemory: boolean;\n /** FTS/vector blend for memory search: 0 = FTS only, 1 = vector only. Default: 0.5. */\n memorySearchAlpha: number;\n /** Store uncompressed originals when caveman is on. Default: false. */\n memoryKeepRaw: boolean;\n /** Auto-prune threshold (max observations). 0 = no limit. Default: 10000. */\n memoryMaxObservations: number;\n /** Seconds of inactivity before auto-closing a session. Default: 7200. */\n memorySessionTimeout: number;\n /** Max observations shown in kirograph_context. Default: 3. */\n memoryContextLimit: number;\n /** Min relevance score to include memory in context. Default: 0.3. */\n memoryContextThreshold: number;\n /** Glob patterns for paths to never capture in memory. Default: []. */\n memoryExcludePatterns: string[];\n /**\n * Reject observation writes that don't conform to the memory schema\n * (unknown `kind`, blank tags) instead of silently accepting them.\n * Applies to `kirograph mem store`, the `kirograph_mem_store` MCP tool,\n * and `MemoryManager.store()` directly. Off by default \u2014 existing\n * free-form writes are unaffected until explicitly opted in.\n * Default: false.\n */\n memoryStrictWrites: boolean;\n /**\n * How `kirograph_mem_compare`/`kirograph mem compare` classifies the\n * relation between two observations.\n * 'agent' \u2014 the calling agent supplies `relation`+`confidence` itself (current behavior).\n * 'jev' \u2014 `relation` becomes optional; when omitted, KiroGraph classifies it via\n * the jev API (see `jevApiKey`) and auto-judges it when confidence is above\n * `memoryRelationConfidenceThreshold`, otherwise leaves it pending for review.\n * 'strands' \u2014 same as 'jev' but classified by a local strands-decider server\n * (see `strandsBaseUrl`) instead of the cloud API; no API key required.\n * Default: 'agent'.\n */\n memoryRelationMode: 'agent' | 'jev' | 'strands';\n /** Confidence (0.0\u20131.0) above which a jev-classified relation is auto-judged instead of left pending. Default: 0.8. */\n memoryRelationConfidenceThreshold: number;\n /**\n * Validate an observation's `fields` (structured data beyond `content`)\n * against a JSON Schema registered per kind at\n * `.kirograph/memory-schemas/<kind>.schema.json`. A kind with no schema\n * file registered is never validated \u2014 schemas are opt-in per kind.\n * Off by default; independent of memoryStrictWrites (that one validates\n * `kind`/`tags`, this one validates `fields`). Default: false.\n */\n memorySchemaValidation: boolean;\n /** Enable watchmen \u2014 auto-synthesize workspace briefs from memory observations. Requires enableMemory. Default: false. */\n enableWatchmen: boolean;\n /** Minimum new observations since last synthesis before watchmenReady fires. Default: 5. */\n watchmenThreshold: number;\n /**\n * How synthesis is performed.\n * 'local' \u2014 runs a local HuggingFace model via @huggingface/transformers (no API cost, works for all tools).\n * 'agent' \u2014 delegates to the active AI agent via askAgent hook (Kiro only, consumes agent tokens).\n * Default: 'local'.\n */\n watchmenSynthesisMode: 'local' | 'agent';\n /** HuggingFace model ID for local synthesis. Only used when watchmenSynthesisMode is 'local'. Default: 'onnx-community/gemma-4-E4B-it-ONNX'. */\n watchmenLocalModel: string;\n /** Enable documentation indexing and navigation. Default: false. */\n enableDocs: boolean;\n /** Glob patterns for documentation files to include. */\n docsInclude: string[];\n /** Glob patterns for documentation files to exclude. */\n docsExclude: string[];\n /** Enable auto-linking of doc sections to code symbols. Default: true. */\n docsLinkCode: boolean;\n /** Max doc sections to include in kirograph_context. 0 = disabled. Default: 0. */\n docsContextLimit: number;\n /** Min relevance score to include a doc section in context. Default: 0.3. */\n docsContextThreshold: number;\n /** Max file size for doc files (bytes). Default: 1MB. */\n docsMaxFileSize: number;\n /** Summarization strategy. Default: 'first-sentence'. */\n docsSummarization: 'embedding' | 'first-sentence' | 'off';\n /** Enable LLM-maintained wiki (entity pages in .kirograph/wiki/). Default: false. */\n enableWiki: boolean;\n /** Wiki synthesis mode. Default: 'agent'. */\n wikiSynthesisMode: 'agent' | 'local';\n /** HuggingFace model for local wiki synthesis. */\n wikiLocalModel: string;\n /** Glob patterns for auto-ingest wiki sources. Default: ['docs/']. */\n wikiSources: string[];\n /**\n * Validate a page's optional YAML frontmatter against a JSON Schema\n * registered per `_type` at `.kirograph/wiki-schemas/<type>.schema.json`.\n * Pages without frontmatter, or with a `_type` that has no schema\n * registered, are never validated \u2014 untyped prose pages are unaffected.\n * Checked by `wiki lint`, reported as `schema_error` issues. Default: false.\n */\n wikiTypedPages: boolean;\n /** Auto-resolve wiki conflicts by source date. Default: false. */\n wikiAutoResolveConflicts: boolean;\n /**\n * How `wiki lint`'s contradiction check works.\n * 'heuristic' \u2014 keyword co-occurrence on FTS-similar pages (current behavior).\n * 'jev' \u2014 asks the jev API whether each FTS-similar pair actually contradicts,\n * flagged when confidence is above `wikiContradictionConfidenceThreshold`.\n * 'strands' \u2014 same as 'jev' but judged by a local strands-decider server\n * (see `strandsBaseUrl`) instead of the cloud API; no API key required.\n * Default: 'heuristic'.\n */\n wikiContradictionMode: 'heuristic' | 'jev' | 'strands';\n /** Confidence (0.0\u20131.0) above which a jev contradiction judgment is reported by `wiki lint`. Default: 0.7. */\n wikiContradictionConfidenceThreshold: number;\n /** Lint frequency: 'weekly' (every ~20 sessions) or 'off'. Default: 'off'. */\n wikiLintFrequency: 'weekly' | 'off';\n /** Max wiki pages to include in kirograph_context. Default: 3. */\n wikiContextLimit: number;\n /** Min FTS score to include wiki page in context. Default: 0.4. */\n wikiContextThreshold: number;\n /** Enable tabular data indexing and querying. Default: false. */\n enableData: boolean;\n /** Glob patterns for data files to include. */\n dataInclude: string[];\n /** Glob patterns for data files to exclude. */\n dataExclude: string[];\n /** Enable auto-linking of data files to code symbols. Default: true. */\n dataLinkCode: boolean;\n /** Max datasets to include in kirograph_context. 0 = disabled. Default: 0. */\n dataContextLimit: number;\n /** Max file size for data files (bytes). Default: 50MB. */\n dataMaxFileSize: number;\n /** Max rows to index per file. Default: 1,000,000. */\n dataMaxRows: number;\n /** Max rows returned per query. Default: 500. */\n dataQueryLimit: number;\n /** Max token budget per response. Default: 8000. */\n dataMaxResponseTokens: number;\n /** Enable security analysis (dependency scanning + vulnerability detection). Default: false. */\n enableSecurity: boolean;\n /** Vulnerability databases to query. Default: ['OSV']. */\n securityDatabases: string[];\n /** Enable AST-level structural pattern matching (SAST) during indexing. Default: false. */\n enablePatterns: boolean;\n /** Enable code health tools (hotspots, dead code, path analysis, type hierarchy). Default: false. */\n enableCodeHealth: boolean;\n /** Enable navigation tools (status, files, impact). Default: false. */\n enableNavigation: boolean;\n /** Enable complexity metrics tools. Default: false. */\n enableComplexity: boolean;\n /** Enable git-context tools (diff_context, commit_context, flows, etc.). Default: false. */\n enableGitContext: boolean;\n /** Enable atomic edit primitive tools (str_replace, insert_at, etc.) and refactor. Default: false. */\n enableEditPrimitives: boolean;\n /** Enable multi-branch graph indexing tools. Default: false. */\n enableBranch: boolean;\n /** @deprecated Dissolved \u2014 tools moved to enableCodeHealth, enableGitContext, enableArchitecture, enableEditPrimitives. Kept in KNOWN_FIELDS for silent backwards compatibility. */\n enableAdvancedAnalysis?: boolean;\n /** Enable agent utility tools (file caching, budget tracking). Default: true. */\n enableAgentUtils: boolean;\n /** Enable general-purpose compression tool (kirograph_compress). Default: false. */\n enableGeneralCompression: boolean;\n /** Derived from shellCompressionLevel \u2014 true when compression is enabled. Controls kirograph_exec. */\n enableShellExec: boolean;\n /** Path to a directory of user-supplied YAML rule files. Merged with bundled library (user rules win on id conflict). Default: undefined. */\n patternLibraryPath: string | undefined;\n /** Minimum severity level for storing pattern matches during index-time analysis. Default: 'low'. */\n patternSeverityThreshold: 'critical' | 'high' | 'medium' | 'low';\n /** Auto-run vulnerability enrichment after manifest parsing. Default: true. */\n securityAutoEnrich: boolean;\n /** Max age in days for vulnerability data before showing a staleness warning. Default: 7. */\n securityEnrichMaxAgeDays: number;\n /**\n * How `attack-surface`'s isAuthenticated detection works.\n * 'heuristic' \u2014 substring match against a fixed name list (current behavior);\n * a custom-named auth wrapper is silently misclassified as unauthenticated.\n * 'jev' \u2014 when the heuristic finds no auth pattern, asks the jev API to\n * confirm/override using the route + call-path names as context. The\n * heuristic's positive matches are trusted as-is (not re-checked) to keep\n * this cheap \u2014 jev only resolves the heuristic's false-negative gap.\n * 'strands' \u2014 same as 'jev' but asks a local strands-decider server (see\n * `strandsBaseUrl`) instead of the cloud API; no API key required.\n * Default: 'heuristic'.\n */\n securityAuthDetectionMode: 'heuristic' | 'jev' | 'strands';\n /** Confidence (0.0\u20131.0) above which a jev auth judgment overrides the heuristic's \"not authenticated\" default. Default: 0.6. */\n securityAuthConfidenceThreshold: number;\n /**\n * License policy for dependency compliance.\n * deny: licenses to block (build fails / command exits non-zero).\n * warn: licenses to flag as warnings.\n * Patterns support wildcards: GPL-* matches GPL-2.0, GPL-3.0, etc.\n * Default: { deny: [], warn: [] }.\n */\n securityLicensePolicy: {\n deny: string[];\n warn: string[];\n };\n /** Context budget governance settings. */\n contextBudget?: {\n maxTokensPerSession: number;\n warnAt: number;\n throttleAt: number;\n };\n /**\n * API key for jev (TypeSafe System One, https://docs.typesafe.ai) \u2014 a fast\n * typed-classification model used by the opt-in `*Mode: 'jev'` toggles\n * (`memoryRelationMode`, `wikiContradictionMode`, `securityAuthDetectionMode`).\n * Falls back to the JEV_API_KEY environment variable when unset here.\n * Prefer the env var for a real key; this field exists mainly so a project\n * (or a test config) can point at a local mock server. Default: undefined.\n */\n jevApiKey?: string;\n /** Override the jev API base URL \u2014 for a local mock server in tests, or a self-hosted deployment. Default: https://api.typesafe.ai. */\n jevBaseUrl?: string;\n /** jev model ID. Default: 'jev-latest'. */\n jevModel: string;\n /**\n * Base URL of a local strands-decider server (https://github.com/strands-labs/strands-decider),\n * started with `strands-decider serve <checkpoint> --port 8000`. Used by the\n * `*Mode: 'strands'` toggles \u2014 the local, no-API-key alternative to jev.\n * Default: http://127.0.0.1:8000.\n */\n strandsBaseUrl?: string;\n /**\n * The model/checkpoint the strands-decider server was started with. Only\n * echoed back in the request; the server uses whatever checkpoint it loaded.\n * Default: 'StrandsAgents/strands-decider-2B-hobson-v19'.\n */\n strandsModel: string;\n}\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst KIROGRAPH_DIR = '.kirograph';\nconst CONFIG_FILE = 'config.json';\n\nconst KNOWN_FIELDS = new Set<string>([\n 'version', 'languages', 'include', 'exclude', 'maxFileSize',\n 'extractDocstrings', 'trackCallSites', 'enableEmbeddings', 'embeddingModel', 'embeddingDim',\n 'useVecIndex', 'semanticEngine', 'turboquantMemDocs', 'turboquantBits', 'turbovecMemDocs', 'turbovecBits', 'typesenseDashboard', 'qdrantDashboard',\n 'minLogLevel', 'frameworkHints', 'fuzzyResolutionThreshold',\n 'enableArchitecture', 'architectureLayers', 'cavemanMode', 'shellCompressionLevel', 'syncWarningThreshold',\n 'enableMemory', 'memorySearchAlpha', 'memoryKeepRaw', 'memoryMaxObservations',\n 'memorySessionTimeout', 'memoryContextLimit', 'memoryContextThreshold', 'memoryExcludePatterns', 'memoryStrictWrites',\n 'memoryRelationMode', 'memoryRelationConfidenceThreshold', 'memorySchemaValidation',\n 'enableWatchmen', 'watchmenThreshold', 'watchmenSynthesisMode', 'watchmenLocalModel',\n 'enableWiki', 'wikiSynthesisMode', 'wikiLocalModel', 'wikiSources', 'wikiTypedPages',\n 'wikiAutoResolveConflicts', 'wikiLintFrequency', 'wikiContextLimit', 'wikiContextThreshold',\n 'wikiContradictionMode', 'wikiContradictionConfidenceThreshold',\n 'enableDocs', 'docsInclude', 'docsExclude', 'docsLinkCode',\n 'docsContextLimit', 'docsContextThreshold', 'docsMaxFileSize', 'docsSummarization',\n 'enableData', 'dataInclude', 'dataExclude', 'dataLinkCode',\n 'dataContextLimit', 'dataMaxFileSize', 'dataMaxRows', 'dataQueryLimit', 'dataMaxResponseTokens',\n 'enableSecurity', 'securityDatabases', 'securityAutoEnrich', 'securityEnrichMaxAgeDays', 'securityLicensePolicy',\n 'securityAuthDetectionMode', 'securityAuthConfidenceThreshold',\n 'enablePatterns', 'patternLibraryPath', 'patternSeverityThreshold',\n 'enableCodeHealth', 'enableNavigation', 'enableComplexity', 'enableGitContext',\n 'enableEditPrimitives', 'enableBranch',\n 'enableAgentUtils', 'enableGeneralCompression',\n 'contextBudget',\n 'jevApiKey', 'jevBaseUrl', 'jevModel',\n 'strandsBaseUrl', 'strandsModel',\n // Legacy aliases / derived fields (accepted but ignored or recomputed)\n 'enableCompression', 'compressionLevel', 'enableShellExec',\n // Deprecated: dissolved flag kept here so old configs don't warn\n 'enableAdvancedAnalysis',\n]);\n\nconst LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error']);\n\n// \u2500\u2500 ReDoS-safe regex check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Returns false if the pattern is potentially dangerous (ReDoS risk) or too long.\n * Checks for catastrophic backtracking patterns like (a+)+ or (a|a)+.\n */\nexport function isSafeRegex(pattern: string): boolean {\n if (pattern.length > 100) return false;\n // Detect nested quantifiers: (x+)+ or (x*)+ or (x+)* etc.\n if (/\\([^)]*[+*][^)]*\\)[+*?]/.test(pattern)) return false;\n // Detect alternation with overlap: (a|a)+ style\n if (/\\([^)]*\\|[^)]*\\)[+*]/.test(pattern)) return false;\n return true;\n}\n\n// \u2500\u2500 Default config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function createDefaultConfig(_projectRoot?: string): KiroGraphConfig {\n return {\n version: 2,\n languages: [],\n include: [],\n exclude: [\n '**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.kirograph/**',\n // Compiled / minified output and build artifacts \u2014 not meaningful source to index,\n // and large bundles can crash the parser (issue #33). '*.min.js' was previously\n // non-recursive (root-only); use '**/' so nested bundles are matched.\n '**/*.min.js', '**/*.min.css', '**/*.bundle.js', '**/*.map',\n '**/out/**', '**/.next/**', '**/.nuxt/**', '**/.vite/**', '**/.svelte-kit/**',\n '**/public/build/**', '**/Resources/Public/**',\n ],\n maxFileSize: 1_048_576,\n extractDocstrings: false,\n trackCallSites: false,\n enableEmbeddings: false,\n embeddingModel: 'nomic-ai/nomic-embed-text-v1.5',\n embeddingDim: 768,\n useVecIndex: false,\n semanticEngine: 'cosine',\n turboquantMemDocs: false,\n turboquantBits: 3,\n turbovecMemDocs: false,\n turbovecBits: 4,\n typesenseDashboard: false,\n qdrantDashboard: false,\n minLogLevel: 'warn',\n frameworkHints: [],\n fuzzyResolutionThreshold: 0.5,\n enableArchitecture: false,\n cavemanMode: 'off',\n shellCompressionLevel: 'off',\n syncWarningThreshold: 10,\n enableMemory: false,\n memorySearchAlpha: 0.5,\n memoryKeepRaw: false,\n memoryMaxObservations: 10000,\n memorySessionTimeout: 7200,\n memoryContextLimit: 3,\n memoryContextThreshold: 0.3,\n memoryExcludePatterns: [],\n memoryStrictWrites: false,\n memoryRelationMode: 'agent' as const,\n memoryRelationConfidenceThreshold: 0.8,\n memorySchemaValidation: false,\n enableWatchmen: false,\n watchmenThreshold: 5,\n watchmenSynthesisMode: 'local',\n watchmenLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n enableWiki: false,\n wikiSynthesisMode: 'agent' as const,\n wikiLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n wikiSources: ['docs/'],\n wikiTypedPages: false,\n wikiAutoResolveConflicts: false,\n wikiLintFrequency: 'off' as const,\n wikiContextLimit: 3,\n wikiContextThreshold: 0.4,\n wikiContradictionMode: 'heuristic' as const,\n wikiContradictionConfidenceThreshold: 0.7,\n enableDocs: false,\n docsInclude: ['**/*.md', '**/*.mdx', '**/*.rst', '**/*.adoc', '**/*.asciidoc', '**/*.rdoc', '**/*.org', '**/*.cheatmd', 'docs/**/*.txt', 'docs/**/*.html'],\n docsExclude: ['node_modules/**', '**/CHANGELOG*', '**/LICENSE*', '**/CHANGES*', 'dist/**', 'build/**', 'coverage/**', '.git/**', '**/generated/**', '**/auto-generated/**', '**/vendor/**', '_build/**'],\n docsLinkCode: true,\n docsContextLimit: 0,\n docsContextThreshold: 0.3,\n docsMaxFileSize: 1_048_576,\n docsSummarization: 'first-sentence',\n enableData: false,\n dataInclude: ['**/*.csv', '**/*.tsv', '**/*.jsonl', '**/*.ndjson', '**/*.xlsx', '**/*.xls', '**/*.parquet', 'data/**/*.json', '**/*.pdf'],\n dataExclude: ['node_modules/**', 'dist/**', 'build/**', '.git/**', '**/package-lock.json', '**/yarn.lock', '**/pnpm-lock.yaml', '**/tsconfig.json', '**/jsconfig.json', 'coverage/**', '**/generated/**'],\n dataLinkCode: true,\n dataContextLimit: 0,\n dataMaxFileSize: 52_428_800,\n dataMaxRows: 1_000_000,\n dataQueryLimit: 500,\n dataMaxResponseTokens: 8000,\n enableSecurity: false,\n securityDatabases: ['OSV'],\n securityAutoEnrich: true,\n securityEnrichMaxAgeDays: 7,\n securityAuthDetectionMode: 'heuristic' as const,\n securityAuthConfidenceThreshold: 0.6,\n securityLicensePolicy: { deny: [], warn: [] },\n enablePatterns: false,\n patternLibraryPath: undefined,\n patternSeverityThreshold: 'low',\n enableCodeHealth: false,\n enableNavigation: false,\n enableComplexity: false,\n enableGitContext: false,\n enableEditPrimitives: false,\n enableBranch: false,\n enableAgentUtils: true,\n enableGeneralCompression: false,\n enableShellExec: false,\n jevApiKey: undefined,\n jevBaseUrl: undefined,\n jevModel: 'jev-latest',\n strandsBaseUrl: undefined,\n strandsModel: 'StrandsAgents/strands-decider-2B-hobson-v19',\n };\n}\n\n// \u2500\u2500 Validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function validateConfig(config: unknown): KiroGraphConfig {\n const defaults = createDefaultConfig();\n\n if (typeof config !== 'object' || config === null) {\n return defaults;\n }\n\n const raw = config as Record<string, unknown>;\n\n // Warn about unknown fields\n for (const key of Object.keys(raw)) {\n if (!KNOWN_FIELDS.has(key)) {\n logWarn(`Unknown config field: ${key}`);\n }\n }\n\n // Validate and coerce each field\n const version = typeof raw.version === 'number' ? raw.version : defaults.version;\n const languages = Array.isArray(raw.languages) && raw.languages.every(l => typeof l === 'string')\n ? (raw.languages as string[])\n : defaults.languages;\n const maxFileSize = typeof raw.maxFileSize === 'number' && raw.maxFileSize > 0\n ? raw.maxFileSize\n : defaults.maxFileSize;\n const extractDocstrings = typeof raw.extractDocstrings === 'boolean'\n ? raw.extractDocstrings\n : defaults.extractDocstrings;\n const trackCallSites = typeof raw.trackCallSites === 'boolean'\n ? raw.trackCallSites\n : defaults.trackCallSites;\n const enableEmbeddings = typeof raw.enableEmbeddings === 'boolean'\n ? raw.enableEmbeddings\n : defaults.enableEmbeddings;\n const embeddingModel = typeof raw.embeddingModel === 'string' && raw.embeddingModel.length > 0\n ? raw.embeddingModel\n : defaults.embeddingModel;\n const embeddingDim = typeof raw.embeddingDim === 'number' && raw.embeddingDim > 0\n ? raw.embeddingDim\n : defaults.embeddingDim;\n const useVecIndex = typeof raw.useVecIndex === 'boolean'\n ? raw.useVecIndex\n : defaults.useVecIndex;\n const SEMANTIC_ENGINES = new Set(['cosine', 'turboquant', 'turbovec', 'sqlite-vec', 'orama', 'pglite', 'lancedb', 'qdrant', 'typesense']);\n // useVecIndex is a legacy alias: if set and no explicit semanticEngine, map it\n const semanticEngine = typeof raw.semanticEngine === 'string' && SEMANTIC_ENGINES.has(raw.semanticEngine)\n ? (raw.semanticEngine as KiroGraphConfig['semanticEngine'])\n : useVecIndex ? 'sqlite-vec' : defaults.semanticEngine;\n const turboquantMemDocs = typeof raw.turboquantMemDocs === 'boolean'\n ? raw.turboquantMemDocs\n : defaults.turboquantMemDocs;\n const turboquantBits = typeof raw.turboquantBits === 'number'\n && raw.turboquantBits >= 1 && raw.turboquantBits <= 8\n ? Math.round(raw.turboquantBits)\n : defaults.turboquantBits;\n const turbovecMemDocs = typeof raw.turbovecMemDocs === 'boolean'\n ? raw.turbovecMemDocs\n : defaults.turbovecMemDocs;\n const TURBOVEC_BIT_WIDTHS = new Set([2, 3, 4]);\n const turbovecBits = typeof raw.turbovecBits === 'number' && TURBOVEC_BIT_WIDTHS.has(Math.round(raw.turbovecBits))\n ? Math.round(raw.turbovecBits)\n : defaults.turbovecBits;\n const typesenseDashboard = typeof raw.typesenseDashboard === 'boolean'\n ? raw.typesenseDashboard\n : defaults.typesenseDashboard;\n const qdrantDashboard = typeof raw.qdrantDashboard === 'boolean'\n ? raw.qdrantDashboard\n : defaults.qdrantDashboard;\n const minLogLevel = typeof raw.minLogLevel === 'string' && LOG_LEVELS.has(raw.minLogLevel)\n ? (raw.minLogLevel as KiroGraphConfig['minLogLevel'])\n : defaults.minLogLevel;\n const frameworkHints = Array.isArray(raw.frameworkHints) && raw.frameworkHints.every(h => typeof h === 'string')\n ? (raw.frameworkHints as string[])\n : defaults.frameworkHints;\n const fuzzyResolutionThreshold = typeof raw.fuzzyResolutionThreshold === 'number'\n && raw.fuzzyResolutionThreshold >= 0\n && raw.fuzzyResolutionThreshold <= 1\n ? raw.fuzzyResolutionThreshold\n : defaults.fuzzyResolutionThreshold;\n const enableArchitecture = typeof raw.enableArchitecture === 'boolean'\n ? raw.enableArchitecture\n : defaults.enableArchitecture;\n const architectureLayers = _validateArchitectureLayers(raw.architectureLayers);\n const CAVEMAN_MODES = new Set(['off', 'lite', 'full', 'ultra']);\n const cavemanMode = typeof raw.cavemanMode === 'string' && CAVEMAN_MODES.has(raw.cavemanMode)\n ? (raw.cavemanMode as KiroGraphConfig['cavemanMode'])\n : defaults.cavemanMode;\n const COMPRESSION_LEVELS = new Set(['off', 'normal', 'aggressive', 'ultra']);\n // Support legacy field names: enableCompression (boolean) and compressionLevel (string)\n let shellCompressionLevel: KiroGraphConfig['shellCompressionLevel'];\n if (typeof raw.shellCompressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.shellCompressionLevel)) {\n shellCompressionLevel = raw.shellCompressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.compressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.compressionLevel)) {\n shellCompressionLevel = raw.compressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.enableCompression === 'boolean') {\n shellCompressionLevel = raw.enableCompression ? 'normal' : 'off';\n } else {\n shellCompressionLevel = defaults.shellCompressionLevel;\n }\n const syncWarningThreshold = typeof raw.syncWarningThreshold === 'number' && raw.syncWarningThreshold >= 0\n ? Math.round(raw.syncWarningThreshold)\n : defaults.syncWarningThreshold;\n\n // \u2500\u2500 Memory config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableMemory = typeof raw.enableMemory === 'boolean'\n ? raw.enableMemory\n : defaults.enableMemory;\n const memorySearchAlpha = typeof raw.memorySearchAlpha === 'number'\n && raw.memorySearchAlpha >= 0 && raw.memorySearchAlpha <= 1\n ? raw.memorySearchAlpha\n : defaults.memorySearchAlpha;\n const memoryKeepRaw = typeof raw.memoryKeepRaw === 'boolean'\n ? raw.memoryKeepRaw\n : defaults.memoryKeepRaw;\n const memoryMaxObservations = typeof raw.memoryMaxObservations === 'number' && raw.memoryMaxObservations >= 0\n ? Math.round(raw.memoryMaxObservations)\n : defaults.memoryMaxObservations;\n const memorySessionTimeout = typeof raw.memorySessionTimeout === 'number' && raw.memorySessionTimeout > 0\n ? Math.round(raw.memorySessionTimeout)\n : defaults.memorySessionTimeout;\n const memoryContextLimit = typeof raw.memoryContextLimit === 'number' && raw.memoryContextLimit >= 0\n ? Math.round(raw.memoryContextLimit)\n : defaults.memoryContextLimit;\n const memoryContextThreshold = typeof raw.memoryContextThreshold === 'number'\n && raw.memoryContextThreshold >= 0 && raw.memoryContextThreshold <= 1\n ? raw.memoryContextThreshold\n : defaults.memoryContextThreshold;\n const memoryExcludePatterns = Array.isArray(raw.memoryExcludePatterns)\n && raw.memoryExcludePatterns.every((p: unknown) => typeof p === 'string')\n ? (raw.memoryExcludePatterns as string[])\n : defaults.memoryExcludePatterns;\n const memoryStrictWrites = typeof raw.memoryStrictWrites === 'boolean'\n ? raw.memoryStrictWrites\n : defaults.memoryStrictWrites;\n const MEMORY_RELATION_MODES = new Set(['agent', 'jev', 'strands']);\n const memoryRelationMode = typeof raw.memoryRelationMode === 'string' && MEMORY_RELATION_MODES.has(raw.memoryRelationMode)\n ? (raw.memoryRelationMode as KiroGraphConfig['memoryRelationMode'])\n : defaults.memoryRelationMode;\n const memoryRelationConfidenceThreshold = typeof raw.memoryRelationConfidenceThreshold === 'number'\n && raw.memoryRelationConfidenceThreshold >= 0 && raw.memoryRelationConfidenceThreshold <= 1\n ? raw.memoryRelationConfidenceThreshold\n : defaults.memoryRelationConfidenceThreshold;\n const memorySchemaValidation = typeof raw.memorySchemaValidation === 'boolean'\n ? raw.memorySchemaValidation\n : defaults.memorySchemaValidation;\n\n // \u2500\u2500 Watchmen config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableWatchmen = typeof raw.enableWatchmen === 'boolean'\n ? raw.enableWatchmen\n : defaults.enableWatchmen;\n const watchmenThreshold = typeof raw.watchmenThreshold === 'number' && raw.watchmenThreshold > 0\n ? Math.round(raw.watchmenThreshold)\n : defaults.watchmenThreshold;\n const WATCHMEN_SYNTHESIS_MODES = new Set(['local', 'agent']);\n const watchmenSynthesisMode = typeof raw.watchmenSynthesisMode === 'string' && WATCHMEN_SYNTHESIS_MODES.has(raw.watchmenSynthesisMode)\n ? (raw.watchmenSynthesisMode as KiroGraphConfig['watchmenSynthesisMode'])\n : defaults.watchmenSynthesisMode;\n const watchmenLocalModel = typeof raw.watchmenLocalModel === 'string' && raw.watchmenLocalModel.length > 0\n ? raw.watchmenLocalModel\n : defaults.watchmenLocalModel;\n\n // \u2500\u2500 Wiki config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableWiki = typeof raw.enableWiki === 'boolean' ? raw.enableWiki : defaults.enableWiki;\n const wikiSynthesisMode = raw.wikiSynthesisMode === 'local' ? 'local' as const : 'agent' as const;\n const wikiLocalModel = typeof raw.wikiLocalModel === 'string' ? raw.wikiLocalModel : defaults.wikiLocalModel;\n const wikiSources = Array.isArray(raw.wikiSources) ? raw.wikiSources : defaults.wikiSources;\n const wikiTypedPages = typeof raw.wikiTypedPages === 'boolean' ? raw.wikiTypedPages : defaults.wikiTypedPages;\n const wikiAutoResolveConflicts = typeof raw.wikiAutoResolveConflicts === 'boolean' ? raw.wikiAutoResolveConflicts : defaults.wikiAutoResolveConflicts;\n const wikiLintFrequency = raw.wikiLintFrequency === 'weekly' ? 'weekly' as const : 'off' as const;\n const wikiContextLimit = typeof raw.wikiContextLimit === 'number' ? raw.wikiContextLimit : defaults.wikiContextLimit;\n const wikiContextThreshold = typeof raw.wikiContextThreshold === 'number' ? raw.wikiContextThreshold : defaults.wikiContextThreshold;\n const WIKI_CONTRADICTION_MODES = new Set(['heuristic', 'jev', 'strands']);\n const wikiContradictionMode = typeof raw.wikiContradictionMode === 'string' && WIKI_CONTRADICTION_MODES.has(raw.wikiContradictionMode)\n ? (raw.wikiContradictionMode as KiroGraphConfig['wikiContradictionMode'])\n : 'heuristic' as const;\n const wikiContradictionConfidenceThreshold = typeof raw.wikiContradictionConfidenceThreshold === 'number'\n && raw.wikiContradictionConfidenceThreshold >= 0 && raw.wikiContradictionConfidenceThreshold <= 1\n ? raw.wikiContradictionConfidenceThreshold\n : defaults.wikiContradictionConfidenceThreshold;\n\n // \u2500\u2500 Docs config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableDocs = typeof raw.enableDocs === 'boolean'\n ? raw.enableDocs\n : defaults.enableDocs;\n const docsInclude = Array.isArray(raw.docsInclude)\n && raw.docsInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsInclude as string[])\n : defaults.docsInclude;\n const docsExclude = Array.isArray(raw.docsExclude)\n && raw.docsExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsExclude as string[])\n : defaults.docsExclude;\n const docsLinkCode = typeof raw.docsLinkCode === 'boolean'\n ? raw.docsLinkCode\n : defaults.docsLinkCode;\n const docsContextLimit = typeof raw.docsContextLimit === 'number' && raw.docsContextLimit >= 0\n ? Math.round(raw.docsContextLimit)\n : defaults.docsContextLimit;\n const docsContextThreshold = typeof raw.docsContextThreshold === 'number'\n && raw.docsContextThreshold >= 0 && raw.docsContextThreshold <= 1\n ? raw.docsContextThreshold\n : defaults.docsContextThreshold;\n const docsMaxFileSize = typeof raw.docsMaxFileSize === 'number' && raw.docsMaxFileSize > 0\n ? raw.docsMaxFileSize\n : defaults.docsMaxFileSize;\n const DOCS_SUMMARIZATION_MODES = new Set(['embedding', 'first-sentence', 'off']);\n const docsSummarization = typeof raw.docsSummarization === 'string' && DOCS_SUMMARIZATION_MODES.has(raw.docsSummarization)\n ? (raw.docsSummarization as KiroGraphConfig['docsSummarization'])\n : defaults.docsSummarization;\n\n // \u2500\u2500 Data config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableData = typeof raw.enableData === 'boolean' ? raw.enableData : defaults.enableData;\n const dataInclude = Array.isArray(raw.dataInclude) && raw.dataInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataInclude as string[]) : defaults.dataInclude;\n const dataExclude = Array.isArray(raw.dataExclude) && raw.dataExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataExclude as string[]) : defaults.dataExclude;\n const dataLinkCode = typeof raw.dataLinkCode === 'boolean' ? raw.dataLinkCode : defaults.dataLinkCode;\n const dataContextLimit = typeof raw.dataContextLimit === 'number' && raw.dataContextLimit >= 0\n ? Math.round(raw.dataContextLimit) : defaults.dataContextLimit;\n const dataMaxFileSize = typeof raw.dataMaxFileSize === 'number' && raw.dataMaxFileSize > 0\n ? raw.dataMaxFileSize : defaults.dataMaxFileSize;\n const dataMaxRows = typeof raw.dataMaxRows === 'number' && raw.dataMaxRows > 0\n ? Math.round(raw.dataMaxRows) : defaults.dataMaxRows;\n const dataQueryLimit = typeof raw.dataQueryLimit === 'number' && raw.dataQueryLimit > 0\n ? Math.min(Math.round(raw.dataQueryLimit), 500) : defaults.dataQueryLimit;\n const dataMaxResponseTokens = typeof raw.dataMaxResponseTokens === 'number' && raw.dataMaxResponseTokens > 0\n ? Math.round(raw.dataMaxResponseTokens) : defaults.dataMaxResponseTokens;\n\n // \u2500\u2500 Security config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let enableSecurity: boolean;\n if (typeof raw.enableSecurity === 'boolean') {\n enableSecurity = raw.enableSecurity;\n } else {\n if (raw.enableSecurity !== undefined) {\n logWarn('Invalid config field enableSecurity: expected boolean, applying default (false)');\n }\n enableSecurity = defaults.enableSecurity;\n }\n\n let securityAutoEnrich: boolean;\n if (typeof raw.securityAutoEnrich === 'boolean') {\n securityAutoEnrich = raw.securityAutoEnrich;\n } else {\n if (raw.securityAutoEnrich !== undefined) {\n logWarn('Invalid config field securityAutoEnrich: expected boolean, applying default (true)');\n }\n securityAutoEnrich = defaults.securityAutoEnrich;\n }\n\n let securityEnrichMaxAgeDays: number;\n if (typeof raw.securityEnrichMaxAgeDays === 'number' && raw.securityEnrichMaxAgeDays > 0) {\n securityEnrichMaxAgeDays = raw.securityEnrichMaxAgeDays;\n } else {\n if (raw.securityEnrichMaxAgeDays !== undefined) {\n logWarn('Invalid config field securityEnrichMaxAgeDays: expected positive number, applying default (7)');\n }\n securityEnrichMaxAgeDays = defaults.securityEnrichMaxAgeDays;\n }\n\n const SECURITY_AUTH_DETECTION_MODES = new Set(['heuristic', 'jev', 'strands']);\n const securityAuthDetectionMode = typeof raw.securityAuthDetectionMode === 'string' && SECURITY_AUTH_DETECTION_MODES.has(raw.securityAuthDetectionMode)\n ? (raw.securityAuthDetectionMode as KiroGraphConfig['securityAuthDetectionMode'])\n : 'heuristic' as const;\n const securityAuthConfidenceThreshold = typeof raw.securityAuthConfidenceThreshold === 'number'\n && raw.securityAuthConfidenceThreshold >= 0 && raw.securityAuthConfidenceThreshold <= 1\n ? raw.securityAuthConfidenceThreshold\n : defaults.securityAuthConfidenceThreshold;\n\n const SUPPORTED_SECURITY_DATABASES = new Set(['OSV']);\n let securityDatabases: string[];\n if (Array.isArray(raw.securityDatabases) && raw.securityDatabases.every((d: unknown) => typeof d === 'string')) {\n const valid = (raw.securityDatabases as string[]).filter(d => {\n if (!SUPPORTED_SECURITY_DATABASES.has(d)) {\n logWarn(`Unsupported security database \"${d}\" in securityDatabases, ignoring`);\n return false;\n }\n return true;\n });\n securityDatabases = valid.length > 0 ? valid : defaults.securityDatabases;\n } else {\n if (raw.securityDatabases !== undefined) {\n logWarn('Invalid config field securityDatabases: expected array of strings, applying default ([\"OSV\"])');\n }\n securityDatabases = defaults.securityDatabases;\n }\n\n let securityLicensePolicy: KiroGraphConfig['securityLicensePolicy'];\n if (raw.securityLicensePolicy && typeof raw.securityLicensePolicy === 'object' && !Array.isArray(raw.securityLicensePolicy)) {\n const rawPolicy = raw.securityLicensePolicy as Record<string, unknown>;\n const deny = Array.isArray(rawPolicy.deny) && rawPolicy.deny.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.deny as string[])\n : defaults.securityLicensePolicy.deny;\n const warn = Array.isArray(rawPolicy.warn) && rawPolicy.warn.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.warn as string[])\n : defaults.securityLicensePolicy.warn;\n securityLicensePolicy = { deny, warn };\n } else {\n if (raw.securityLicensePolicy !== undefined) {\n logWarn('Invalid config field securityLicensePolicy: expected object with deny/warn arrays, applying default');\n }\n securityLicensePolicy = defaults.securityLicensePolicy;\n }\n\n // \u2500\u2500 Patterns config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let enablePatterns: boolean;\n if (typeof raw.enablePatterns === 'boolean') {\n enablePatterns = raw.enablePatterns;\n } else {\n if (raw.enablePatterns !== undefined) {\n logWarn('Invalid config field enablePatterns: expected boolean, applying default (false)');\n }\n enablePatterns = defaults.enablePatterns;\n }\n\n let patternLibraryPath: string | undefined;\n if (raw.patternLibraryPath === undefined || raw.patternLibraryPath === null) {\n patternLibraryPath = undefined;\n } else if (typeof raw.patternLibraryPath === 'string') {\n patternLibraryPath = raw.patternLibraryPath;\n } else {\n logWarn('Invalid config field patternLibraryPath: expected string or undefined, applying default (undefined)');\n patternLibraryPath = defaults.patternLibraryPath;\n }\n\n const PATTERN_SEVERITY_LEVELS = new Set(['critical', 'high', 'medium', 'low']);\n let patternSeverityThreshold: KiroGraphConfig['patternSeverityThreshold'];\n if (typeof raw.patternSeverityThreshold === 'string' && PATTERN_SEVERITY_LEVELS.has(raw.patternSeverityThreshold)) {\n patternSeverityThreshold = raw.patternSeverityThreshold as KiroGraphConfig['patternSeverityThreshold'];\n } else {\n if (raw.patternSeverityThreshold !== undefined) {\n logWarn('Invalid config field patternSeverityThreshold: expected critical|high|medium|low, applying default (low)');\n }\n patternSeverityThreshold = defaults.patternSeverityThreshold;\n }\n\n // \u2500\u2500 Tool group flags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const enableCodeHealth = typeof raw.enableCodeHealth === 'boolean'\n ? raw.enableCodeHealth\n : defaults.enableCodeHealth;\n const enableNavigation = typeof raw.enableNavigation === 'boolean'\n ? raw.enableNavigation\n : defaults.enableNavigation;\n const enableComplexity = typeof raw.enableComplexity === 'boolean'\n ? raw.enableComplexity\n : defaults.enableComplexity;\n const enableGitContext = typeof raw.enableGitContext === 'boolean'\n ? raw.enableGitContext\n : defaults.enableGitContext;\n const enableEditPrimitives = typeof raw.enableEditPrimitives === 'boolean'\n ? raw.enableEditPrimitives\n : defaults.enableEditPrimitives;\n const enableBranch = typeof raw.enableBranch === 'boolean'\n ? raw.enableBranch\n : defaults.enableBranch;\n // enableAdvancedAnalysis is deprecated \u2014 silently accepted, not applied\n const enableAgentUtils = typeof raw.enableAgentUtils === 'boolean'\n ? raw.enableAgentUtils\n : defaults.enableAgentUtils;\n const enableGeneralCompression = typeof raw.enableGeneralCompression === 'boolean'\n ? raw.enableGeneralCompression\n : defaults.enableGeneralCompression;\n\n // Dependency constraint: enableSecurity requires enableArchitecture\n let finalEnableArchitecture = enableArchitecture;\n if (enableSecurity && !enableArchitecture) {\n logWarn('enableSecurity requires enableArchitecture \\u2014 auto-enabling architecture analysis');\n finalEnableArchitecture = true;\n }\n\n // \u2500\u2500 jev config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const jevApiKey = typeof raw.jevApiKey === 'string' && raw.jevApiKey.length > 0 ? raw.jevApiKey : undefined;\n const jevBaseUrl = typeof raw.jevBaseUrl === 'string' && raw.jevBaseUrl.length > 0 ? raw.jevBaseUrl : undefined;\n const jevModel = typeof raw.jevModel === 'string' && raw.jevModel.length > 0 ? raw.jevModel : defaults.jevModel;\n\n // \u2500\u2500 strands-decider config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const strandsBaseUrl = typeof raw.strandsBaseUrl === 'string' && raw.strandsBaseUrl.length > 0 ? raw.strandsBaseUrl : undefined;\n const strandsModel = typeof raw.strandsModel === 'string' && raw.strandsModel.length > 0 ? raw.strandsModel : defaults.strandsModel;\n\n // \u2500\u2500 Context budget config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let contextBudget: KiroGraphConfig['contextBudget'] | undefined;\n if (raw.contextBudget && typeof raw.contextBudget === 'object' && !Array.isArray(raw.contextBudget)) {\n const cb = raw.contextBudget as Record<string, unknown>;\n contextBudget = {\n maxTokensPerSession: typeof cb.maxTokensPerSession === 'number' && cb.maxTokensPerSession > 0\n ? Math.round(cb.maxTokensPerSession) : 100_000,\n warnAt: typeof cb.warnAt === 'number' && cb.warnAt > 0\n ? Math.round(cb.warnAt) : 80_000,\n throttleAt: typeof cb.throttleAt === 'number' && cb.throttleAt > 0\n ? Math.round(cb.throttleAt) : 95_000,\n };\n }\n\n // Validate glob patterns \u2014 exclude unsafe regex patterns\n const include = _validatePatterns(raw.include, defaults.include);\n const exclude = _validatePatterns(raw.exclude, defaults.exclude);\n\n return {\n version,\n languages,\n include,\n exclude,\n maxFileSize,\n extractDocstrings,\n trackCallSites,\n enableEmbeddings,\n embeddingModel,\n embeddingDim,\n useVecIndex,\n semanticEngine,\n turboquantMemDocs,\n turboquantBits,\n turbovecMemDocs,\n turbovecBits,\n typesenseDashboard,\n qdrantDashboard,\n minLogLevel,\n frameworkHints,\n fuzzyResolutionThreshold,\n enableArchitecture: finalEnableArchitecture,\n cavemanMode,\n shellCompressionLevel,\n syncWarningThreshold,\n enableMemory,\n memorySearchAlpha,\n memoryKeepRaw,\n memoryMaxObservations,\n memorySessionTimeout,\n memoryContextLimit,\n memoryContextThreshold,\n memoryExcludePatterns,\n memoryStrictWrites,\n memoryRelationMode,\n memoryRelationConfidenceThreshold,\n memorySchemaValidation,\n enableWatchmen: enableWatchmen && enableMemory,\n watchmenThreshold,\n watchmenSynthesisMode,\n watchmenLocalModel,\n enableWiki,\n wikiSynthesisMode,\n wikiLocalModel,\n wikiSources,\n wikiTypedPages,\n wikiAutoResolveConflicts,\n wikiLintFrequency,\n wikiContextLimit,\n wikiContextThreshold,\n wikiContradictionMode,\n wikiContradictionConfidenceThreshold,\n enableDocs,\n docsInclude,\n docsExclude,\n docsLinkCode,\n docsContextLimit,\n docsContextThreshold,\n docsMaxFileSize,\n docsSummarization,\n enableData,\n dataInclude,\n dataExclude,\n dataLinkCode,\n dataContextLimit,\n dataMaxFileSize,\n dataMaxRows,\n dataQueryLimit,\n dataMaxResponseTokens,\n enableSecurity,\n securityDatabases,\n securityAutoEnrich,\n securityEnrichMaxAgeDays,\n securityAuthDetectionMode,\n securityAuthConfidenceThreshold,\n securityLicensePolicy,\n enablePatterns,\n patternLibraryPath,\n patternSeverityThreshold,\n enableCodeHealth,\n enableNavigation,\n enableComplexity,\n enableGitContext,\n enableEditPrimitives,\n enableBranch,\n enableAgentUtils,\n enableGeneralCompression,\n enableShellExec: shellCompressionLevel !== 'off',\n jevModel,\n strandsModel,\n ...(architectureLayers !== undefined ? { architectureLayers } : {}),\n ...(contextBudget !== undefined ? { contextBudget } : {}),\n ...(jevApiKey !== undefined ? { jevApiKey } : {}),\n ...(jevBaseUrl !== undefined ? { jevBaseUrl } : {}),\n ...(strandsBaseUrl !== undefined ? { strandsBaseUrl } : {}),\n };\n}\n\nfunction _validateArchitectureLayers(raw: unknown): Record<string, string[]> | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw !== 'object' || Array.isArray(raw)) return undefined;\n const result: Record<string, string[]> = {};\n for (const [key, val] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof key !== 'string') continue;\n if (!Array.isArray(val)) continue;\n const patterns = val.filter((p): p is string => typeof p === 'string' && isSafeRegex(p));\n if (patterns.length > 0) result[key] = patterns;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction _validatePatterns(raw: unknown, fallback: string[]): string[] {\n if (!Array.isArray(raw)) return fallback;\n const valid: string[] = [];\n for (const p of raw) {\n if (typeof p !== 'string') continue;\n if (!isSafeRegex(p)) {\n logWarn(`Unsafe regex pattern skipped: ${p}`);\n continue;\n }\n valid.push(p);\n }\n return valid;\n}\n\n// \u2500\u2500 Migration helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Upgrades shallow exclude patterns (e.g. \"node_modules/**\") to recursive ones\n * (e.g. \"** /node_modules/**\") so nested directories are excluded at any depth.\n */\nconst SHALLOW_TO_RECURSIVE: Record<string, string> = {\n 'node_modules/**': '**/node_modules/**',\n 'dist/**': '**/dist/**',\n 'build/**': '**/build/**',\n '.git/**': '**/.git/**',\n '.kirograph/**': '**/.kirograph/**',\n};\n\nfunction migrateExcludePatterns(patterns: string[]): string[] {\n return patterns.map(p => SHALLOW_TO_RECURSIVE[p] ?? p);\n}\n\n// \u2500\u2500 Load / Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Load KEY=VALUE pairs from `.kirograph/.env` into process.env \u2014 e.g. JEV_API_KEY\n * for the opt-in jev integrations. A minimal parser (one assignment per line,\n * '#' comments, optional surrounding quotes) rather than a dotenv dependency,\n * to keep secrets out of the CLI's own dependency surface. A variable already\n * set in the real environment is never overridden \u2014 the .env file is a\n * fallback default, not an override. `.kirograph/.env` should be gitignored.\n */\nfunction loadDotEnv(kirographDir: string): void {\n let content: string;\n try {\n content = fs.readFileSync(path.join(kirographDir, '.env'), 'utf8');\n } catch {\n return; // no .env file \u2014 nothing to do\n }\n\n for (const rawLine of content.split('\\n')) {\n const line = rawLine.trim();\n if (!line || line.startsWith('#')) continue;\n const eq = line.indexOf('=');\n if (eq === -1) continue;\n const key = line.slice(0, eq).trim();\n if (!key) continue;\n let value = line.slice(eq + 1).trim();\n if (value.length >= 2 && ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\")))) {\n value = value.slice(1, -1);\n }\n if (process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n}\n\nexport async function loadConfig(projectRoot: string): Promise<KiroGraphConfig> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n\n loadDotEnv(dir);\n\n if (!fs.existsSync(cfgPath)) {\n // Create default config file\n const defaults = createDefaultConfig(projectRoot);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, defaults);\n return defaults;\n }\n\n let raw: unknown;\n try {\n const text = await fs.promises.readFile(cfgPath, 'utf8');\n raw = JSON.parse(text);\n } catch (err) {\n logError('Config parse error', { path: cfgPath, error: err instanceof Error ? err.message : String(err) });\n return createDefaultConfig(projectRoot);\n }\n\n const config = validateConfig(raw);\n\n // Migrate v1 \u2192 v2: upgrade shallow exclude patterns to recursive\n if (config.version < 2) {\n config.version = 2;\n config.exclude = migrateExcludePatterns(config.exclude);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n }\n\n return config;\n}\n\nexport async function saveConfig(projectRoot: string, config: KiroGraphConfig): Promise<void> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n}\n\nasync function _writeAtomic(cfgPath: string, config: KiroGraphConfig): Promise<void> {\n const tmp = cfgPath + '.tmp';\n await fs.promises.writeFile(tmp, JSON.stringify(config, null, 2), 'utf8');\n await fs.promises.rename(tmp, cfgPath);\n}\n\n// \u2500\u2500 Update helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function updateConfig(\n projectRoot: string,\n patch: Partial<KiroGraphConfig>\n): Promise<KiroGraphConfig> {\n const current = await loadConfig(projectRoot);\n const updated = validateConfig({ ...current, ...patch });\n await saveConfig(projectRoot, updated);\n return updated;\n}\n\nexport async function addIncludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.include);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, include: [...config.include, ...toAdd] });\n}\n\nexport async function addExcludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.exclude);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, exclude: [...config.exclude, ...toAdd] });\n}\n\n// \u2500\u2500 File inclusion check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function shouldIncludeFile(config: KiroGraphConfig, relPath: string): boolean {\n // Check exclude patterns first\n for (const pattern of config.exclude) {\n if (picomatch(pattern)(relPath)) return false;\n }\n // If include patterns are specified, file must match at least one\n if (config.include.length > 0) {\n return config.include.some(pattern => picomatch(pattern)(relPath));\n }\n return true;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["picomatch"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/jev/client.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph \u2014 jev (TypeSafe System One) client\n *\n * Thin HTTP client for https://docs.typesafe.ai's fast typed-classification\n * model. Used by opt-in \"jev mode\" toggles across the codebase (memory\n * relation judging, wiki contradiction detection, attack-surface auth\n * detection) as a cheaper/faster alternative to delegating a narrow\n * classification decision to a full agent turn.\n */\nimport type { JevQuestion, JevResponse } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.typesafe.ai';\nconst DEFAULT_MODEL = 'jev-latest';\nconst DEFAULT_TIMEOUT_MS = 15000;\n\nexport class JevError extends Error {\n constructor(message: string, public readonly status?: number) {\n super(message);\n this.name = 'JevError';\n }\n}\n\nexport interface JevClientOptions {\n apiKey: string;\n /** Override for testing / self-hosted deployments. Default: https://api.typesafe.ai */\n baseUrl?: string;\n /** Default: jev-latest */\n model?: string;\n timeoutMs?: number;\n}\n\nexport class JevClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly model: string;\n private readonly timeoutMs: number;\n\n constructor(opts: JevClientOptions) {\n if (!opts.apiKey) {\n throw new JevError('jev API key is required');\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n this.model = opts.model ?? DEFAULT_MODEL;\n this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Ask one or more typed questions about a piece of state in a single\n * request \u2014 the API evaluates them in parallel, so callers should batch\n * multiple questions about the same state rather than issuing separate calls.\n */\n async ask(state: string, questions: Record<string, JevQuestion>): Promise<JevResponse> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(`${this.baseUrl}/v1/systemone`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ state, model: this.model, questions }),\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n throw new JevError(`jev request timed out after ${this.timeoutMs}ms`);\n }\n throw new JevError(`jev request failed: ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(timeout);\n }\n\n if (!res.ok) {\n let detail = '';\n try { detail = await res.text(); } catch { /* ignore */ }\n throw new JevError(`jev request failed (${res.status})${detail ? `: ${detail}` : ''}`, res.status);\n }\n\n return await res.json() as JevResponse;\n }\n}\n\n/** Minimal shape of the config fields JevClient needs \u2014 avoids importing the full KiroGraphConfig type. */\nexport interface JevConfigLike {\n jevApiKey?: string;\n jevBaseUrl?: string;\n jevModel?: string;\n}\n\n/**\n * Build a JevClient from KiroGraph config, falling back to the JEV_API_KEY\n * env var when `jevApiKey` isn't set in .kirograph/config.json (config.json\n * is often committed to source control \u2014 a config field is provided mainly\n * for pointing at a local mock server in tests).\n */\nexport function createJevClientFromConfig(config: JevConfigLike): JevClient {\n const apiKey = config.jevApiKey || process.env.JEV_API_KEY;\n if (!apiKey) {\n throw new JevError(\n 'jev API key not set \u2014 set the JEV_API_KEY environment variable, or \"jevApiKey\" in .kirograph/config.json',\n );\n }\n return new JevClient({ apiKey, baseUrl: config.jevBaseUrl, model: config.jevModel });\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,MAAM,mBAAmB;AACzB,MAAM,gBAAgB;AACtB,MAAM,qBAAqB;AAEpB,MAAM,iBAAiB,MAAM;AAAA,EAClC,YAAY,SAAiC,QAAiB;AAC5D,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAWO,MAAM,UAAU;AAAA,EAMrB,YAAY,MAAwB;AAClC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,SAAS,yBAAyB;AAAA,IAC9C;AACA,SAAK,SAAS,KAAK;AACnB,SAAK,WAAW,KAAK,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACpE,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,YAAY,KAAK,aAAa;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAI,OAAe,WAA8D;AACrF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AAEnE,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,MAAM,GAAG,KAAK,OAAO,iBAAiB;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,iBAAiB,UAAU,KAAK,MAAM;AAAA,UACtC,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,QAC5D,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,cAAM,IAAI,SAAS,+BAA+B,KAAK,SAAS,IAAI;AAAA,MACtE;AACA,YAAM,IAAI,SAAS,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAC9F,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,UAAI,SAAS;AACb,UAAI;AAAE,iBAAS,MAAM,IAAI,KAAK;AAAA,MAAG,QAAQ;AAAA,MAAe;AACxD,YAAM,IAAI,SAAS,uBAAuB,IAAI,MAAM,IAAI,SAAS,KAAK,MAAM,KAAK,EAAE,IAAI,IAAI,MAAM;AAAA,IACnG;AAEA,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB;AACF;AAeO,SAAS,0BAA0B,QAAkC;AAC1E,QAAM,SAAS,OAAO,aAAa,QAAQ,IAAI;AAC/C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,IAAI,UAAU,EAAE,QAAQ,SAAS,OAAO,YAAY,OAAO,OAAO,SAAS,CAAC;AACrF;",
4
+ "sourcesContent": ["/**\n * KiroGraph \u2014 jev (TypeSafe System One) client\n *\n * Thin HTTP client for https://docs.typesafe.ai's fast typed-classification\n * model. Used by opt-in \"jev mode\" toggles across the codebase (memory\n * relation judging, wiki contradiction detection, attack-surface auth\n * detection) as a cheaper/faster alternative to delegating a narrow\n * classification decision to a full agent turn.\n */\nimport type { DecisionClient, JevQuestion, JevResponse } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.typesafe.ai';\nconst DEFAULT_MODEL = 'jev-latest';\nconst DEFAULT_TIMEOUT_MS = 15000;\n\nexport class JevError extends Error {\n constructor(message: string, public readonly status?: number) {\n super(message);\n this.name = 'JevError';\n }\n}\n\nexport interface JevClientOptions {\n apiKey: string;\n /** Override for testing / self-hosted deployments. Default: https://api.typesafe.ai */\n baseUrl?: string;\n /** Default: jev-latest */\n model?: string;\n timeoutMs?: number;\n}\n\nexport class JevClient implements DecisionClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly model: string;\n private readonly timeoutMs: number;\n\n constructor(opts: JevClientOptions) {\n if (!opts.apiKey) {\n throw new JevError('jev API key is required');\n }\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n this.model = opts.model ?? DEFAULT_MODEL;\n this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n /**\n * Ask one or more typed questions about a piece of state in a single\n * request \u2014 the API evaluates them in parallel, so callers should batch\n * multiple questions about the same state rather than issuing separate calls.\n */\n async ask(state: string, questions: Record<string, JevQuestion>): Promise<JevResponse> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), this.timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(`${this.baseUrl}/v1/systemone`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ state, model: this.model, questions }),\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === 'AbortError') {\n throw new JevError(`jev request timed out after ${this.timeoutMs}ms`);\n }\n throw new JevError(`jev request failed: ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(timeout);\n }\n\n if (!res.ok) {\n let detail = '';\n try { detail = await res.text(); } catch { /* ignore */ }\n throw new JevError(`jev request failed (${res.status})${detail ? `: ${detail}` : ''}`, res.status);\n }\n\n return await res.json() as JevResponse;\n }\n}\n\n/** Minimal shape of the config fields JevClient needs \u2014 avoids importing the full KiroGraphConfig type. */\nexport interface JevConfigLike {\n jevApiKey?: string;\n jevBaseUrl?: string;\n jevModel?: string;\n}\n\n/**\n * Build a JevClient from KiroGraph config, falling back to the JEV_API_KEY\n * env var when `jevApiKey` isn't set in .kirograph/config.json (config.json\n * is often committed to source control \u2014 a config field is provided mainly\n * for pointing at a local mock server in tests).\n */\nexport function createJevClientFromConfig(config: JevConfigLike): JevClient {\n const apiKey = config.jevApiKey || process.env.JEV_API_KEY;\n if (!apiKey) {\n throw new JevError(\n 'jev API key not set \u2014 set the JEV_API_KEY environment variable, or \"jevApiKey\" in .kirograph/config.json',\n );\n }\n return new JevClient({ apiKey, baseUrl: config.jevBaseUrl, model: config.jevModel });\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,MAAM,mBAAmB;AACzB,MAAM,gBAAgB;AACtB,MAAM,qBAAqB;AAEpB,MAAM,iBAAiB,MAAM;AAAA,EAClC,YAAY,SAAiC,QAAiB;AAC5D,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAWO,MAAM,UAAoC;AAAA,EAM/C,YAAY,MAAwB;AAClC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,SAAS,yBAAyB;AAAA,IAC9C;AACA,SAAK,SAAS,KAAK;AACnB,SAAK,WAAW,KAAK,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACpE,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,YAAY,KAAK,aAAa;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAI,OAAe,WAA8D;AACrF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AAEnE,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,MAAM,GAAG,KAAK,OAAO,iBAAiB;AAAA,QAChD,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,iBAAiB,UAAU,KAAK,MAAM;AAAA,UACtC,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,OAAO,OAAO,KAAK,OAAO,UAAU,CAAC;AAAA,QAC5D,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,cAAM,IAAI,SAAS,+BAA+B,KAAK,SAAS,IAAI;AAAA,MACtE;AACA,YAAM,IAAI,SAAS,uBAAuB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAC9F,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,UAAI,SAAS;AACb,UAAI;AAAE,iBAAS,MAAM,IAAI,KAAK;AAAA,MAAG,QAAQ;AAAA,MAAe;AACxD,YAAM,IAAI,SAAS,uBAAuB,IAAI,MAAM,IAAI,SAAS,KAAK,MAAM,KAAK,EAAE,IAAI,IAAI,MAAM;AAAA,IACnG;AAEA,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB;AACF;AAeO,SAAS,0BAA0B,QAAkC;AAC1E,QAAM,SAAS,OAAO,aAAa,QAAQ,IAAI;AAC/C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,IAAI,UAAU,EAAE,QAAQ,SAAS,OAAO,YAAY,OAAO,OAAO,SAAS,CAAC;AACrF;",
6
6
  "names": []
7
7
  }