kirograph 1.3.0 → 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 (42) hide show
  1. package/README.md +4 -3
  2. package/dist/bin/commands/attack-surface.js +3 -1
  3. package/dist/bin/commands/attack-surface.js.map +2 -2
  4. package/dist/bin/commands/help.js +1 -1
  5. package/dist/bin/commands/help.js.map +2 -2
  6. package/dist/bin/commands/memory.js +4 -4
  7. package/dist/bin/commands/memory.js.map +2 -2
  8. package/dist/bin/commands/security-export.js +3 -1
  9. package/dist/bin/commands/security-export.js.map +2 -2
  10. package/dist/bin/commands/wiki.js +2 -0
  11. package/dist/bin/commands/wiki.js.map +2 -2
  12. package/dist/bin/installer/config-prompt.js +13 -9
  13. package/dist/bin/installer/config-prompt.js.map +2 -2
  14. package/dist/bin/installer/index.js +34 -8
  15. package/dist/bin/installer/index.js.map +2 -2
  16. package/dist/bin/kirograph.js +1 -1
  17. package/dist/config.js +15 -5
  18. package/dist/config.js.map +2 -2
  19. package/dist/jev/client.js.map +2 -2
  20. package/dist/jev/factory.js +36 -0
  21. package/dist/jev/factory.js.map +7 -0
  22. package/dist/jev/strands-client.js +89 -0
  23. package/dist/jev/strands-client.js.map +7 -0
  24. package/dist/jev/types.js.map +1 -1
  25. package/dist/mcp/handlers/memory.js +4 -3
  26. package/dist/mcp/handlers/memory.js.map +2 -2
  27. package/dist/mcp/handlers/security.js +3 -1
  28. package/dist/mcp/handlers/security.js.map +2 -2
  29. package/dist/mcp/handlers/wiki.js +2 -0
  30. package/dist/mcp/handlers/wiki.js.map +2 -2
  31. package/dist/memory/index.js +6 -4
  32. package/dist/memory/index.js.map +2 -2
  33. package/dist/memory/relation-jev.js.map +1 -1
  34. package/dist/security/attack-surface.js +6 -6
  35. package/dist/security/attack-surface.js.map +2 -2
  36. package/dist/security/auth-detection-jev.js.map +1 -1
  37. package/dist/wiki/contradiction-jev.js.map +1 -1
  38. package/dist/wiki/index.js +12 -6
  39. package/dist/wiki/index.js.map +2 -2
  40. package/dist/wiki/lint.js +3 -3
  41. package/dist/wiki/lint.js.map +2 -2
  42. package/package.json +1 -1
@@ -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 * 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 * Default: 'agent'.\n */\n memoryRelationMode: 'agent' | 'jev';\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 * Default: 'heuristic'.\n */\n wikiContradictionMode: 'heuristic' | 'jev';\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 * Default: 'heuristic'.\n */\n securityAuthDetectionMode: 'heuristic' | 'jev';\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\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 // 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 };\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']);\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 wikiContradictionMode = raw.wikiContradictionMode === 'jev' ? 'jev' as const : '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 securityAuthDetectionMode = raw.securityAuthDetectionMode === 'jev' ? 'jev' as const : '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 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 ...(architectureLayers !== undefined ? { architectureLayers } : {}),\n ...(contextBudget !== undefined ? { contextBudget } : {}),\n ...(jevApiKey !== undefined ? { jevApiKey } : {}),\n ...(jevBaseUrl !== undefined ? { jevBaseUrl } : {}),\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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",
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
  }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var factory_exports = {};
20
+ __export(factory_exports, {
21
+ createDecisionClient: () => createDecisionClient
22
+ });
23
+ module.exports = __toCommonJS(factory_exports);
24
+ async function createDecisionClient(backend, config) {
25
+ if (backend === "strands") {
26
+ const { createStrandsClientFromConfig } = await Promise.resolve().then(() => require("./strands-client.js"));
27
+ return createStrandsClientFromConfig(config);
28
+ }
29
+ const { createJevClientFromConfig } = await Promise.resolve().then(() => require("./client.js"));
30
+ return createJevClientFromConfig(config);
31
+ }
32
+ // Annotate the CommonJS export names for ESM import in node:
33
+ 0 && (module.exports = {
34
+ createDecisionClient
35
+ });
36
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/jev/factory.ts"],
4
+ "sourcesContent": ["/**\n * KiroGraph \u2014 decision-client factory\n *\n * Selects the typed-classification backend for the opt-in `*Mode` toggles.\n * Both backends implement the same DecisionClient contract, so each consumer\n * (memory relation judging, wiki contradiction detection, attack-surface auth\n * detection) builds its client through here and stays backend-agnostic.\n *\n * 'jev' \u2192 JevClient (TypeSafe System One, cloud, needs JEV_API_KEY)\n * 'strands' \u2192 StrandsClient (strands-decider, local server, no API key)\n *\n * Any other mode value ('agent' / 'heuristic') means classification is not\n * delegated to a model at all, and this factory should not be called.\n */\nimport type { DecisionClient } from './types';\n\n/** The two model-backed classification modes shared across memory/wiki/security. */\nexport type DecisionBackend = 'jev' | 'strands';\n\n/** Config fields either backend might read. A superset of both *ConfigLike shapes. */\nexport interface DecisionConfigLike {\n jevApiKey?: string;\n jevBaseUrl?: string;\n jevModel?: string;\n strandsBaseUrl?: string;\n strandsModel?: string;\n}\n\n/**\n * Build the DecisionClient for the given backend. Throws for jev when no API\n * key is resolvable (via config or the JEV_API_KEY env var); strands never\n * throws here since it needs no credential.\n */\nexport async function createDecisionClient(\n backend: DecisionBackend,\n config: DecisionConfigLike,\n): Promise<DecisionClient> {\n if (backend === 'strands') {\n const { createStrandsClientFromConfig } = await Promise.resolve().then(() => require('./strands-client.js'));\n return createStrandsClientFromConfig(config);\n }\n const { createJevClientFromConfig } = await Promise.resolve().then(() => require('./client.js'));\n return createJevClientFromConfig(config);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCA,eAAsB,qBACpB,SACA,QACyB;AACzB,MAAI,YAAY,WAAW;AACzB,UAAM,EAAE,8BAA8B,IAAI,MAAM,QAAQ,QAAQ,EAAE,KAAK,MAAM,QAAQ,qBAAqB,CAAC;AAC3G,WAAO,8BAA8B,MAAM;AAAA,EAC7C;AACA,QAAM,EAAE,0BAA0B,IAAI,MAAM,QAAQ,QAAQ,EAAE,KAAK,MAAM,QAAQ,aAAa,CAAC;AAC/F,SAAO,0BAA0B,MAAM;AACzC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var strands_client_exports = {};
20
+ __export(strands_client_exports, {
21
+ StrandsClient: () => StrandsClient,
22
+ StrandsError: () => StrandsError,
23
+ createStrandsClientFromConfig: () => createStrandsClientFromConfig
24
+ });
25
+ module.exports = __toCommonJS(strands_client_exports);
26
+ const DEFAULT_BASE_URL = "http://127.0.0.1:8000";
27
+ const DEFAULT_MODEL = "StrandsAgents/strands-decider-2B-hobson-v19";
28
+ const DEFAULT_TIMEOUT_MS = 15e3;
29
+ class StrandsError extends Error {
30
+ constructor(message, status) {
31
+ super(message);
32
+ this.status = status;
33
+ this.name = "StrandsError";
34
+ }
35
+ }
36
+ class StrandsClient {
37
+ constructor(opts = {}) {
38
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
39
+ this.model = opts.model ?? DEFAULT_MODEL;
40
+ this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
41
+ }
42
+ /**
43
+ * Ask one or more typed questions about a piece of state in a single
44
+ * request. The server encodes the state once and broadcasts it across the
45
+ * question batch, so callers should batch multiple questions about the same
46
+ * state rather than issuing separate calls.
47
+ */
48
+ async ask(state, questions) {
49
+ const controller = new AbortController();
50
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
51
+ let res;
52
+ try {
53
+ res = await fetch(`${this.baseUrl}/v1/systemone`, {
54
+ method: "POST",
55
+ headers: { "Content-Type": "application/json" },
56
+ body: JSON.stringify({ state, model: this.model, questions }),
57
+ signal: controller.signal
58
+ });
59
+ } catch (err) {
60
+ if (err instanceof Error && err.name === "AbortError") {
61
+ throw new StrandsError(`strands-decider request timed out after ${this.timeoutMs}ms`);
62
+ }
63
+ throw new StrandsError(
64
+ `strands-decider request failed: ${err instanceof Error ? err.message : String(err)} (is the server running? start it with "strands-decider serve <checkpoint> --port 8000")`
65
+ );
66
+ } finally {
67
+ clearTimeout(timeout);
68
+ }
69
+ if (!res.ok) {
70
+ let detail = "";
71
+ try {
72
+ detail = await res.text();
73
+ } catch {
74
+ }
75
+ throw new StrandsError(`strands-decider request failed (${res.status})${detail ? `: ${detail}` : ""}`, res.status);
76
+ }
77
+ return await res.json();
78
+ }
79
+ }
80
+ function createStrandsClientFromConfig(config) {
81
+ return new StrandsClient({ baseUrl: config.strandsBaseUrl, model: config.strandsModel });
82
+ }
83
+ // Annotate the CommonJS export names for ESM import in node:
84
+ 0 && (module.exports = {
85
+ StrandsClient,
86
+ StrandsError,
87
+ createStrandsClientFromConfig
88
+ });
89
+ //# sourceMappingURL=strands-client.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/jev/strands-client.ts"],
4
+ "sourcesContent": ["/**\n * KiroGraph \u2014 strands-decider client\n *\n * Thin HTTP client for a local strands-decider server\n * (https://github.com/strands-labs/strands-decider), a small, fast typed-\n * classification model (\"system one\"). It is the local, self-hosted\n * alternative to the cloud jev backend behind the opt-in `*Mode` toggles\n * (memory relation judging, wiki contradiction detection, attack-surface auth\n * detection).\n *\n * strands-decider's `POST /v1/systemone` endpoint is wire-compatible with\n * jev's \u2014 same `{ state, model, questions }` body and the same\n * choice/score/noul answer shapes \u2014 so this client shares the DecisionClient\n * contract and the jev request/response types. The only differences from\n * JevClient: it talks to a local server (default http://127.0.0.1:8000),\n * started with `strands-decider serve`, and sends no Authorization header\n * (the server binds to localhost and has no authentication).\n */\nimport type { DecisionClient, JevQuestion, JevResponse } from './types';\n\n/** strands-decider serve defaults to 127.0.0.1:8000. */\nconst DEFAULT_BASE_URL = 'http://127.0.0.1:8000';\n/** The published reference checkpoint; the server also accepts a local checkpoint path. */\nconst DEFAULT_MODEL = 'StrandsAgents/strands-decider-2B-hobson-v19';\nconst DEFAULT_TIMEOUT_MS = 15000;\n\nexport class StrandsError extends Error {\n constructor(message: string, public readonly status?: number) {\n super(message);\n this.name = 'StrandsError';\n }\n}\n\nexport interface StrandsClientOptions {\n /** Base URL of the running strands-decider server. Default: http://127.0.0.1:8000 */\n baseUrl?: string;\n /** Model/checkpoint the server was started with. Default: StrandsAgents/strands-decider-2B-hobson-v19 */\n model?: string;\n timeoutMs?: number;\n}\n\nexport class StrandsClient implements DecisionClient {\n private readonly baseUrl: string;\n private readonly model: string;\n private readonly timeoutMs: number;\n\n constructor(opts: StrandsClientOptions = {}) {\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. The server encodes the state once and broadcasts it across the\n * question batch, so callers should batch multiple questions about the same\n * 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: { 'Content-Type': 'application/json' },\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 StrandsError(`strands-decider request timed out after ${this.timeoutMs}ms`);\n }\n throw new StrandsError(\n `strands-decider request failed: ${err instanceof Error ? err.message : String(err)} `\n + `(is the server running? start it with \"strands-decider serve <checkpoint> --port 8000\")`,\n );\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 StrandsError(`strands-decider 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 StrandsClient needs. */\nexport interface StrandsConfigLike {\n strandsBaseUrl?: string;\n strandsModel?: string;\n}\n\n/**\n * Build a StrandsClient from KiroGraph config. Unlike jev, there is no API\n * key to resolve \u2014 the server is local and unauthenticated \u2014 so this never\n * throws for a missing credential; a wrong/missing server surfaces as a\n * connection error at request time instead.\n */\nexport function createStrandsClientFromConfig(config: StrandsConfigLike): StrandsClient {\n return new StrandsClient({ baseUrl: config.strandsBaseUrl, model: config.strandsModel });\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,MAAM,mBAAmB;AAEzB,MAAM,gBAAgB;AACtB,MAAM,qBAAqB;AAEpB,MAAM,qBAAqB,MAAM;AAAA,EACtC,YAAY,SAAiC,QAAiB;AAC5D,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAUO,MAAM,cAAwC;AAAA,EAKnD,YAAY,OAA6B,CAAC,GAAG;AAC3C,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;AAAA,EAQA,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,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,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,aAAa,2CAA2C,KAAK,SAAS,IAAI;AAAA,MACtF;AACA,YAAM,IAAI;AAAA,QACR,mCAAmC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAErF;AAAA,IACF,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,aAAa,mCAAmC,IAAI,MAAM,IAAI,SAAS,KAAK,MAAM,KAAK,EAAE,IAAI,IAAI,MAAM;AAAA,IACnH;AAEA,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB;AACF;AAcO,SAAS,8BAA8B,QAA0C;AACtF,SAAO,IAAI,cAAc,EAAE,SAAS,OAAO,gBAAgB,OAAO,OAAO,aAAa,CAAC;AACzF;",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/jev/types.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph \u2014 jev (TypeSafe System One) client types\n *\n * Mirrors the real API shape at https://docs.typesafe.ai:\n * POST /v1/systemone\n * { state: string, model: string, questions: { [id]: JevQuestion } }\n * \u2192 { model: string, answers: { [id]: JevAnswer }, usage?: {...} }\n */\n\n/** Choice: selects one of a fixed set of named categories. Max 255 options. */\nexport interface JevChoiceQuestion {\n type: 'choice';\n instructions: string;\n /** category name \u2192 description shown to the model */\n criteria: Record<string, string>;\n}\n\n/** Score: a calibrated numeric level chosen from an ordered set of 2\u201310 descriptions. */\nexport interface JevScoreQuestion {\n type: 'score';\n instructions: string;\n /** ordered level descriptions, low \u2192 high */\n criteria: string[];\n}\n\n/** Noul: a boolean-shaped judgment returned as a 0.0\u20131.0 value. */\nexport interface JevNoulQuestion {\n type: 'noul';\n instructions: string;\n}\n\nexport type JevQuestion = JevChoiceQuestion | JevScoreQuestion | JevNoulQuestion;\n\nexport interface JevChoiceAnswer {\n type: 'choice';\n choice: string;\n confidence?: number;\n probabilities?: Record<string, number>;\n}\n\nexport interface JevScoreAnswer {\n type: 'score';\n score: number;\n confidence?: number;\n legend?: Record<string, string>;\n}\n\nexport interface JevNoulAnswer {\n type: 'noul';\n noul: number;\n confidence?: number;\n}\n\nexport type JevAnswer = JevChoiceAnswer | JevScoreAnswer | JevNoulAnswer;\n\nexport interface JevUsage {\n input_tokens: number;\n output_tokens: number;\n}\n\nexport interface JevResponse {\n model: string;\n answers: Record<string, JevAnswer>;\n usage?: JevUsage;\n}\n"],
4
+ "sourcesContent": ["/**\n * KiroGraph \u2014 jev (TypeSafe System One) client types\n *\n * Mirrors the real API shape at https://docs.typesafe.ai:\n * POST /v1/systemone\n * { state: string, model: string, questions: { [id]: JevQuestion } }\n * \u2192 { model: string, answers: { [id]: JevAnswer }, usage?: {...} }\n */\n\n/** Choice: selects one of a fixed set of named categories. Max 255 options. */\nexport interface JevChoiceQuestion {\n type: 'choice';\n instructions: string;\n /** category name \u2192 description shown to the model */\n criteria: Record<string, string>;\n}\n\n/** Score: a calibrated numeric level chosen from an ordered set of 2\u201310 descriptions. */\nexport interface JevScoreQuestion {\n type: 'score';\n instructions: string;\n /** ordered level descriptions, low \u2192 high */\n criteria: string[];\n}\n\n/** Noul: a boolean-shaped judgment returned as a 0.0\u20131.0 value. */\nexport interface JevNoulQuestion {\n type: 'noul';\n instructions: string;\n}\n\nexport type JevQuestion = JevChoiceQuestion | JevScoreQuestion | JevNoulQuestion;\n\nexport interface JevChoiceAnswer {\n type: 'choice';\n choice: string;\n confidence?: number;\n probabilities?: Record<string, number>;\n}\n\nexport interface JevScoreAnswer {\n type: 'score';\n score: number;\n confidence?: number;\n legend?: Record<string, string>;\n}\n\nexport interface JevNoulAnswer {\n type: 'noul';\n noul: number;\n confidence?: number;\n}\n\nexport type JevAnswer = JevChoiceAnswer | JevScoreAnswer | JevNoulAnswer;\n\nexport interface JevUsage {\n input_tokens: number;\n output_tokens: number;\n}\n\nexport interface JevResponse {\n model: string;\n answers: Record<string, JevAnswer>;\n usage?: JevUsage;\n}\n\n/**\n * Backend-agnostic contract for a typed-classification client.\n *\n * Both JevClient (TypeSafe System One, cloud) and StrandsClient\n * (strands-decider, a local server) implement this. The request/response\n * shape is identical across backends \u2014 strands-decider's `POST /v1/systemone`\n * is wire-compatible with jev's \u2014 so consumers depend only on this interface\n * and never on a concrete backend. The classification helpers\n * (classifyRelationWithJev / checkContradictionWithJev / checkAuthWithJev)\n * accept a DecisionClient, so they run unchanged against either backend.\n */\nexport interface DecisionClient {\n ask(state: string, questions: Record<string, JevQuestion>): Promise<JevResponse>;\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }