* refactor(tuning): prune dormant runtime knobs Remove unused tuning controls and adaptive search budget state. Extract testable ONNX slot reconciliation and search telemetry hydration seams, and correct the Apple Silicon sysctl value width. * refactor(vector): retire dormant backends Remove unused FAISS, model-infrastructure, VectorIndexManager, and TurboQuant paths while keeping Simeon PQ and float-vector storage. Migrate unused V2.2 quantized schemas transactionally to V2.3. Databases containing non-default quantized formats or packed-code blobs fail closed with recovery guidance and no mutation. * refactor(plugins): remove legacy SDK tooling Remove the Ghidra and SDK submodules, their bespoke tests, and stale scan exclusions. Retain generic PluginProcess coverage against the repository mock fixture. * build(vector): remove stale FAISS overrides * refactor(ipc): remove dormant FSM snapshots * refactor(ingest): unify bounded KG enqueue * fix(plugins): harden allocation contracts Keep ABI outputs null or fully initialized when allocations fail, and represent empty object payloads without relying on malloc(0). * fix(storage): define empty object reads Return a null buffer with zero length for successful empty-object reads instead of treating malloc(0) as an allocation contract. * refactor(storage): trim through string views * test: prune dormant harness helpers Remove unused readiness and fixture helpers, and keep benchmark client-count doubling in a wide integer domain. * chore(cpp): initialize analyzer-facing locals * build(simeon): advance analyzer cleanup * refactor(config): drop dead daemon client keys * refactor(ipc): inject daemon client transport Socket and in-process execution now share DaemonClient request dispatch, so CLI fallbacks do not need alternate service paths. * refactor(retrieval): route CLI through daemon Search and grep now use the same daemon handlers over socket or in-process transport. Live grep remains an explicit freshness inspection. * refactor(graph): move CLI scope into daemon Graph CLI requests now share daemon handlers across socket and in-process transports. CWD filtering occurs before pagination so scoped totals and pages stay correct. * build: isolate test-only runtime controls * refactor(metadata): decouple lock telemetry * fix(services): return on request timeout * fix(retrieval): enforce workspace scope * fix(graph): scope nodes before pagination * fix(grep): drop binary result lines * fix(daemon): bound checkpoint wait * fix(repair): use KG health checks * fix(storage): always verify compressed CRC * perf(vector): skip unchanged PQ snapshots * build(zyp): exclude bench from default build * build: protect Meson files from formatter * refactor: remove unreachable production APIs * refactor(daemon): remove dormant runtime state * fix(vector): harden daemon provider calls Timed-out coroutines must own their client and requests. Provider discovery must also fail instead of returning synthetic embeddings in production. * refactor(storage): remove unusable adapters * fix(cli): unify in-process add requests * fix(tsan): preserve async worker progress * test(cli): isolate daemon-dependent suites * fix(repair): expose queue backoff progress
852 lines
28 KiB
TOML
852 lines
28 KiB
TOML
# YAMS Configuration Template
|
||
# This file contains all available configuration options with their default values.
|
||
# Copy this file to ~/.config/yams/config.toml and modify as needed.
|
||
#
|
||
# File Location Strategy:
|
||
# - All data files (databases, indexes, WAL, objects) are nested under data_dir by default
|
||
# - Paths can be absolute or relative; relative paths are resolved from data_dir
|
||
# - Use ~ for home directory expansion (e.g., ~/.yams/data)
|
||
|
||
[version]
|
||
config_version = 3
|
||
migrated_from = 0
|
||
migration_date = "2025-01-16"
|
||
|
||
[core]
|
||
# Data storage directory - all other data files nest under this by default
|
||
# ~ will be expanded to home directory
|
||
data_dir = "~/.yams/data"
|
||
# Storage engine: "local" or "distributed" (future)
|
||
storage_engine = "local"
|
||
# Enable Write-Ahead Logging for crash recovery
|
||
enable_wal = true
|
||
# Enable telemetry (anonymous usage statistics)
|
||
enable_telemetry = false
|
||
# Log level: "trace", "debug", "info", "warn", "error"
|
||
log_level = "info"
|
||
|
||
[auth]
|
||
# Path to Ed25519 private key for signing
|
||
private_key_path = "~/.config/yams/keys/ed25519.pem"
|
||
# Path to Ed25519 public key for verification
|
||
public_key_path = "~/.config/yams/keys/ed25519.pub"
|
||
# API keys for authentication (optional)
|
||
api_keys = []
|
||
|
||
[performance]
|
||
# Number of worker threads for parallel operations
|
||
num_worker_threads = 4
|
||
# Size of I/O thread pool
|
||
io_thread_pool_size = 2
|
||
# Maximum concurrent operations
|
||
max_concurrent_operations = 100
|
||
# Enable memory-mapped file access
|
||
enable_memory_mapping = false
|
||
# Total cache size in MB
|
||
cache_size_mb = 512
|
||
|
||
[storage]
|
||
# Storage engine type
|
||
engine = "local"
|
||
# Base path for storage (defaults to core.data_dir)
|
||
base_path = "~/.yams/data"
|
||
# Enable transparent compression
|
||
enable_compression = true
|
||
# Enable content deduplication
|
||
enable_deduplication = true
|
||
# Enable content-defined chunking
|
||
enable_chunking = true
|
||
# CAS object storage directories (relative to base_path/data_dir)
|
||
objects_dir = "objects"
|
||
staging_dir = "staging"
|
||
|
||
[storage.s3]
|
||
# S3 Engine Settings (used if storage.engine = "s3")
|
||
url = ""
|
||
region = "us-east-1"
|
||
endpoint = ""
|
||
access_key = ""
|
||
secret_key = ""
|
||
session_token = ""
|
||
use_path_style = false
|
||
# Behavior when S3 is unreachable: "strict" (error) or "local" (fallback to local engine)
|
||
fallback_policy = "strict"
|
||
# Local data dir to use when falling back; empty = config-level data_dir
|
||
fallback_local_data_dir = ""
|
||
|
||
[storage.s3.r2]
|
||
# Explicit Cloudflare R2 temporary-credential bootstrap mode.
|
||
# Keep auth_mode="direct" for normal S3 key/secret usage.
|
||
auth_mode = "direct"
|
||
api_token = ""
|
||
account_id = ""
|
||
parent_access_key_id = ""
|
||
permission = "object-read-write"
|
||
ttl_seconds = 3600
|
||
|
||
[chunking]
|
||
# Rolling hash window size
|
||
window_size = 48
|
||
# Minimum chunk size in bytes
|
||
min_chunk_size = 1024
|
||
# Maximum chunk size in bytes
|
||
max_chunk_size = 16384
|
||
# Target average chunk size
|
||
average_chunk_size = 8192
|
||
# Hash algorithm for chunk identification
|
||
hash_algorithm = "sha256"
|
||
|
||
[compression]
|
||
# Enable compression for new content
|
||
enable = true
|
||
# Compression algorithm: "zstd" or "lzma"
|
||
algorithm = "zstd"
|
||
# ZSTD compression level (1-22)
|
||
zstd_level = 9
|
||
# LZMA compression level (0-9)
|
||
lzma_level = 6
|
||
# Minimum size to consider for compression
|
||
chunk_threshold = 1024
|
||
# Always compress files larger than this
|
||
always_compress_above = 10485760 # 10MB
|
||
# Never compress files smaller than this
|
||
never_compress_below = 1024 # 1KB
|
||
# Compress content older than N days
|
||
compress_after_days = 1
|
||
# Use LZMA for content older than N days
|
||
archive_after_days = 30
|
||
# Maximum parallel compression operations
|
||
max_concurrent_compressions = 4
|
||
# Use background compression
|
||
async_compression = true
|
||
# Decompression cache entries
|
||
decompression_cache_size = 100
|
||
# Decompression cache size in bytes
|
||
decompression_cache_size_bytes = 536870912 # 512MB
|
||
|
||
[wal]
|
||
# Enable Write-Ahead Logging
|
||
enable = true
|
||
# Directory for WAL files (relative to data_dir if not absolute)
|
||
wal_directory = "wal"
|
||
# Maximum size per log file
|
||
max_log_size = 104857600 # 100MB
|
||
# Sync to disk every N entries
|
||
sync_interval = 1000
|
||
# Maximum time between syncs (ms)
|
||
sync_timeout_ms = 100
|
||
# Compress rotated log files
|
||
compress_old_logs = true
|
||
# Maximum open log files
|
||
max_open_files = 10
|
||
# Batch commits for performance
|
||
enable_group_commit = true
|
||
|
||
[vector_database]
|
||
# Enable vector database for embeddings
|
||
enable = true
|
||
# SQLite database path for vectors (relative to data_dir if not absolute)
|
||
database_path = "vectors.db"
|
||
# Table name for embeddings
|
||
table_name = "document_embeddings"
|
||
# Embedding dimension (new installs default to simeon-default / 1024; existing DBs keep their stored dim)
|
||
embedding_dim = 1024
|
||
# Enable periodic checkpoints
|
||
enable_checkpoints = true
|
||
# Operations between checkpoints
|
||
checkpoint_frequency = 1000
|
||
# Maximum batch size for operations
|
||
max_batch_size = 1000
|
||
# Default similarity threshold for search
|
||
default_similarity_threshold = 0.35
|
||
# Use in-memory database (for testing)
|
||
use_in_memory = false
|
||
# Auto-create database if missing
|
||
auto_create = true
|
||
# Auto-repair on corruption
|
||
auto_repair = true
|
||
# Maximum number of vectors in index (for large corpuses, increase this)
|
||
# Default: 100000. For very large repositories, use 500000 or 1000000
|
||
max_elements = 100000
|
||
|
||
[embeddings]
|
||
# Enable embedding generation
|
||
enable = true
|
||
# Embedding backend: "daemon" or "simeon" (default, in-process, model-free)
|
||
# Env override: YAMS_EMBED_BACKEND
|
||
backend = "simeon"
|
||
# Automatically generate for new documents
|
||
auto_generate = false
|
||
# Automatically trigger embeddings after AddDocument
|
||
auto_on_add = false
|
||
# Preferred embedding model sentinel for the default simeon backend
|
||
preferred_model = "simeon-default"
|
||
# Root directory where optional ONNX plugin models are resolved
|
||
model_path = "~/.yams/models"
|
||
# Path to tokenizer
|
||
tokenizer_path = "models/tokenizer.json"
|
||
# Maximum sequence length
|
||
max_sequence_length = 512
|
||
# Embedding dimension (new installs default to simeon-default / 1024; existing DBs keep their stored dim)
|
||
embedding_dim = 1024
|
||
# Batch size for generation
|
||
batch_size = 32
|
||
# Normalize embedding vectors
|
||
normalize_embeddings = true
|
||
# Use GPU acceleration if available
|
||
enable_gpu = false
|
||
# Number of threads (-1 for auto)
|
||
num_threads = -1
|
||
# Delay between generation batches (ms)
|
||
generation_delay_ms = 1000
|
||
# Track content hash for staleness detection
|
||
track_content_hash = true
|
||
# Model version identifier
|
||
model_version = "1.0.0"
|
||
# Embedding schema version
|
||
embedding_schema_version = 1
|
||
# Keep the optional embedding model resident in memory (ONNX plugin reads this)
|
||
keep_model_hot = true
|
||
# Unload an idle embedding model after this many seconds (0 = never unload)
|
||
model_idle_timeout = 300
|
||
# Preload model on startup
|
||
preload_on_startup = false
|
||
# Maximum memory for model cache (MB)
|
||
max_model_memory_mb = 1024
|
||
|
||
[embeddings.simeon]
|
||
# Simeon encoder presets:
|
||
# - fast: output_dim=384 projection="achlioptas_sparse" lower memory / fastest encode
|
||
# - default: output_dim=1024 projection="fwht" promoted first-class default
|
||
# - quality: output_dim=1024 projection="fwht" pair with [search.simeon_query_router]
|
||
# and [search.simeon_prf] enabled=true once those levers land
|
||
ngram_mode = "char_and_word"
|
||
ngram_min = 3
|
||
ngram_max = 5
|
||
sketch_dim = 4096
|
||
output_dim = 1024
|
||
projection = "fwht"
|
||
l2_normalize = true
|
||
|
||
[embeddings.simeon.bm25]
|
||
enabled = true
|
||
variant = "sab_smooth"
|
||
subword_gamma = 5.0
|
||
max_corpus_docs = 200000
|
||
|
||
[embeddings.simeon.bm25.router]
|
||
# Per-query dispatch between BM25 variants (Atire vs SabSmooth) via
|
||
# simeon::QueryRouter. When enabled, the lexical backend builds both
|
||
# indexes and picks per-query from pre-retrieval features.
|
||
# Preset details: third_party/simeon/docs/router_design.md.
|
||
enabled = true
|
||
preset = "passE_scq0_clar3"
|
||
|
||
[embeddings.selection]
|
||
# Selection strategy: "ranked" (score-based) or "intro_headings" (intro + headings only)
|
||
strategy = "ranked"
|
||
# Chunk selection mode before embedding: "full", "budgeted", or "adaptive"
|
||
mode = "budgeted"
|
||
# Maximum chunks selected per document when mode != "full"
|
||
max_chunks_per_doc = 8
|
||
# Maximum total characters selected per document when mode != "full"
|
||
max_chars_per_doc = 24000
|
||
# Additional score boost for heading-like chunks in adaptive mode
|
||
heading_boost = 1.25
|
||
# Additional score boost for intro/early chunks in adaptive mode
|
||
intro_boost = 0.75
|
||
|
||
# Daemon service and plugins
|
||
[daemon]
|
||
# Enable daemon-managed model provider and plugin auto-loading
|
||
enable = true
|
||
# Auto-start daemon if not running when needed
|
||
auto_start = true
|
||
# Unix domain socket path for IPC
|
||
socket_path = "/tmp/yams-daemon.sock"
|
||
# PID file for daemon process management
|
||
pid_file = "/tmp/yams-daemon.pid"
|
||
# Connection timeout in milliseconds
|
||
connect_timeout_ms = 1000
|
||
# Request timeout in milliseconds
|
||
request_timeout_ms = 5000
|
||
# Auto-load plugins from standard directories (and YAMS_PLUGIN_DIR if set)
|
||
auto_load_plugins = true
|
||
# Optional explicit plugin directory (comment out to use defaults and YAMS_PLUGIN_DIR)
|
||
# plugin_dir = "/usr/local/lib/yams/plugins"
|
||
# Strict plugin root mode: only scan trusted/configured roots, skip built-in defaults.
|
||
# Environment override: YAMS_PLUGIN_DIR_STRICT=1
|
||
plugin_dir_strict = false
|
||
# Enforce plugin naming policy: "relaxed" (accept yams_*_plugin.* or libyams_*_plugin.*)
|
||
# or "spec" (require libyams_*_plugin.*). Environment override: YAMS_PLUGIN_NAME_POLICY.
|
||
plugin_name_policy = "relaxed"
|
||
# Worker threads for daemon (0 = auto)
|
||
worker_threads = 0
|
||
# Max memory in GB the daemon will attempt to use (0 = unlimited)
|
||
max_memory_gb = 0
|
||
# Log level for daemon background service (trace|debug|info|warn|error)
|
||
log_level = "info"
|
||
# Do not rebuild vector schema automatically when embedding dimensions change.
|
||
# Run an explicit foreground vector/embedding repair after choosing the target dimension.
|
||
auto_rebuild_on_dim_mismatch = false
|
||
# Auto-repair missing/corrupted chunks and embeddings in the background
|
||
auto_repair = true
|
||
# Batch size for auto-repair passes
|
||
auto_repair_batch_size = 16
|
||
# Prefer centralized tuning (TuningManager); set to true only if you need legacy in-loop tuner
|
||
# use_legacy_tuner = false
|
||
|
||
[daemon.instrumentation]
|
||
# Runtime instrumentation profile.
|
||
#
|
||
# Profiles:
|
||
# - "normal" / "off" : disable automatic instrumentation behavior.
|
||
# - "memory" / "heap" / "malloc" : reduce concurrent startup maintenance so macOS
|
||
# MallocStackLoggingNoCompact captures the target workload instead of background
|
||
# repair, lexical, and vector-index rebuild noise.
|
||
profile = "normal"
|
||
# Override the profile defaults only when debugging a specific subsystem.
|
||
# suppress_auto_repair = true
|
||
# suppress_simeon_lexical_build = true
|
||
# suppress_vector_index_build = true
|
||
|
||
[daemon.graph_prune]
|
||
# Enable graph prune for snapshot-scoped version nodes
|
||
enabled = false
|
||
# Keep latest N snapshot versions per canonical node
|
||
keep_latest = 3
|
||
# How often to run prune
|
||
interval_minutes = 60
|
||
# Initial delay after startup
|
||
initial_delay_minutes = 10
|
||
|
||
# Centralized tuning knobs (advanced): defaults are safe; uncomment to override
|
||
[tuning]
|
||
# Default tuning preset applied by the daemon. Options: "efficient", "balanced", "aggressive".
|
||
profile = "balanced"
|
||
# Max concurrent in-flight list requests admitted to the daemon
|
||
list_inflight_limit = 8
|
||
# How long list requests wait for admission before erroring (ms)
|
||
list_admission_wait_ms = 200
|
||
# Max concurrent in-flight grep requests
|
||
grep_inflight_limit = 1
|
||
# How long grep requests wait for admission before erroring (ms)
|
||
grep_admission_wait_ms = 20000
|
||
# backpressure_read_pause_ms = 5
|
||
# worker_poll_ms = 150
|
||
# idle_cpu_pct = 10.0
|
||
# idle_mux_low_bytes = 4194304
|
||
# idle_shrink_hold_ms = 5000
|
||
# pool_cooldown_ms = 500
|
||
# pool_scale_step = 1
|
||
# pool_ipc_min = 1
|
||
# pool_ipc_max = 32
|
||
# pool_io_min = 1
|
||
# pool_io_max = 32
|
||
# io_conn_per_thread = 8 # grow IO pool only when activeConn > ioThreads * value
|
||
# post_ingest_threads = 0 # 0 = auto (recommend ~12.5% CPU budget, hard max 4)
|
||
# post_ingest_queue_max = 1000 # bounded queue; producers block when full (backpressure)
|
||
# use_internal_bus_for_repair = false # when true, queue repair embed jobs to internal bus
|
||
# use_internal_bus_for_post_ingest = false # when true, queue post-ingest tasks to internal bus
|
||
# stream_mux_very_high_bytes = 268435456 # 256 MiB
|
||
# stream_mux_high_bytes = 134217728 # 128 MiB
|
||
# stream_mux_light1_bytes = 8388608 # 8 MiB
|
||
# stream_mux_light2_bytes = 33554432 # 32 MiB
|
||
# stream_mux_light3_bytes = 67108864 # 64 MiB
|
||
|
||
# Post-ingest pipeline concurrency caps. Omit a key to let the daemon auto-tune from the CPU
|
||
# budget (see TuneAdvisor::postIngestBudgetedConcurrency). Env vars (YAMS_POST_*_CONCURRENT)
|
||
# take precedence over these config keys. Valid ranges match the setter clamps:
|
||
# total_concurrent: 1..256 ; embed_concurrent, symbol_concurrent: 1..32
|
||
# extraction_concurrent, kg_concurrent: 1..64 ; entity_concurrent, title_concurrent: 1..16
|
||
[tuning.post_ingest]
|
||
# total_concurrent = 8
|
||
# embed_concurrent = 4
|
||
# extraction_concurrent = 3
|
||
# kg_concurrent = 6
|
||
# symbol_concurrent = 3
|
||
# entity_concurrent = 2
|
||
# title_concurrent = 2
|
||
|
||
# Notes:
|
||
# - When [embeddings].enable = false, the daemon automatically disables the model provider
|
||
# and plugin auto-load to reduce startup overhead.
|
||
# - You can override plugin discovery with environment variables:
|
||
# * YAMS_PLUGIN_DIR: an exclusive directory to scan for plugins
|
||
# * YAMS_PLUGIN_DIR_STRICT: when truthy, skip built-in default plugin roots
|
||
# - Trust list persistence file is <data_dir>/plugins.trust
|
||
# - To control client/daemon timeouts at runtime, you can set:
|
||
# * YAMS_REQUEST_TIMEOUT_MS (sets both header/body timeouts in client)
|
||
# * YAMS_HEADER_TIMEOUT_MS / YAMS_BODY_TIMEOUT_MS (client-specific)
|
||
|
||
[embeddings.cache]
|
||
# Enable embedding cache for queries
|
||
enable_query_cache = true
|
||
# Cache size (number of queries)
|
||
cache_size = 1000
|
||
# Cache TTL in seconds
|
||
cache_ttl_seconds = 3600
|
||
# Use LRU eviction
|
||
lru_eviction = true
|
||
|
||
|
||
[vector_index]
|
||
# Index type: "FLAT", "HNSW", "IVF_FLAT", "IVF_PQ", "LSH", "ANNOY"
|
||
type = "HNSW"
|
||
# Vector dimension
|
||
dimension = 384
|
||
# Distance metric: "COSINE", "L2", "INNER_PRODUCT"
|
||
distance_metric = "COSINE"
|
||
# HNSW: connections per node
|
||
hnsw_m = 16
|
||
# HNSW: construction accuracy
|
||
hnsw_ef_construction = 200
|
||
# HNSW: search accuracy
|
||
hnsw_ef_search = 50
|
||
# Normalize vectors before indexing
|
||
normalize_vectors = true
|
||
# Maximum number of vectors
|
||
max_elements = 1000000
|
||
# Save/load index from disk
|
||
enable_persistence = true
|
||
# Index file path
|
||
index_path = "vector_index.bin"
|
||
# Batch size for operations
|
||
batch_size = 1000
|
||
# Use SIMD instructions
|
||
use_simd = true
|
||
# Number of threads (0 for auto)
|
||
num_threads = 0
|
||
# Use delta index for updates
|
||
enable_delta_index = true
|
||
# Merge delta when it reaches this size
|
||
delta_threshold = 1000
|
||
|
||
[search]
|
||
# Default result limit
|
||
default_limit = 10
|
||
# Maximum allowed limit
|
||
max_limit = 100
|
||
# Enable search result caching
|
||
enable_cache = true
|
||
# Cache size (number of queries)
|
||
cache_size = 1000
|
||
# Cache TTL in minutes
|
||
cache_ttl_minutes = 60
|
||
# Reranker backend: "simeon" (default), "onnx", "colbert", or "auto"
|
||
reranker_backend = "simeon"
|
||
# Preferred reranker model (optional)
|
||
reranker_model = ""
|
||
|
||
[search.path_tree]
|
||
# Enable path-tree traversal to serve hierarchical workloads (prefix/semantic/diff)
|
||
enable = false
|
||
# Mode when enabled: "fallback" keeps baseline scans as a safety net, "preferred" makes the tree the default
|
||
mode = "fallback"
|
||
|
||
[search.hybrid]
|
||
# Enable hybrid search
|
||
enable = true
|
||
# Enable knowledge graph scoring
|
||
enable_kg = true
|
||
# Weight for vector similarity
|
||
vector_weight = 0.50
|
||
# Weight for keyword relevance
|
||
keyword_weight = 0.30
|
||
# Weight for KG entity similarity
|
||
kg_entity_weight = 0.10
|
||
# Weight for structural prior
|
||
structural_weight = 0.05
|
||
# Weight for BART classification similarity (when enhanced search enabled)
|
||
classification_weight = 0.05
|
||
# Number of vector results to retrieve
|
||
vector_top_k = 50
|
||
# Number of keyword results to retrieve
|
||
keyword_top_k = 50
|
||
# Final number of results
|
||
final_top_k = 10
|
||
# Fusion strategy: "LINEAR_COMBINATION", "RECIPROCAL_RANK", "CASCADE"
|
||
fusion_strategy = "LINEAR_COMBINATION"
|
||
# RRF constant (for RECIPROCAL_RANK)
|
||
rrf_k = 60.0
|
||
# Enable post-fusion rerank-style score replacement
|
||
enable_reranking = true
|
||
# Number of top fused results eligible for rerank-style passes
|
||
rerank_top_k = 20
|
||
# Enable query expansion
|
||
enable_query_expansion = false
|
||
# Number of expansion terms
|
||
expansion_terms = 5
|
||
# Weight for expansion terms
|
||
expansion_weight = 0.3
|
||
# Maximum KG neighbors to consider
|
||
kg_max_neighbors = 32
|
||
# Maximum KG hops
|
||
kg_max_hops = 1
|
||
# Time budget for KG scoring (ms)
|
||
kg_budget_ms = 20
|
||
# Normalize scores to [0,1]
|
||
normalize_scores = true
|
||
# Generate search explanations
|
||
generate_explanations = true
|
||
# Include debug scores
|
||
include_debug_scores = false
|
||
# Run searches in parallel
|
||
parallel_search = true
|
||
|
||
[search.topology]
|
||
# Product-default topology context around hybrid retrieval. Use "disabled" only as a scientific
|
||
# control or explicit operator override.
|
||
mode = "hybrid_assist"
|
||
# Observe the routed projection while preserving the global ANN result set.
|
||
vector_policy = "shadow"
|
||
# Minimum selected-cluster prefix when adaptive routing is enabled
|
||
min_clusters = 1
|
||
# Max number of clusters considered when routing a weak query
|
||
max_clusters = 2
|
||
# Cap ranked lexical documents used as sparse routing evidence
|
||
max_seed_documents = 32
|
||
# Maximum dense representatives evaluated per cluster (0 = all stored representatives)
|
||
representative_limit = 0
|
||
# Grow the selected prefix while route scores remain this close to the best (0 = fixed max_clusters)
|
||
adaptive_probe_score_gap = 0.0
|
||
# Abstain from narrowing when the selected/excluded score boundary is smaller (0 = disabled)
|
||
narrow_min_boundary_margin = 0.20
|
||
# Max number of candidate docs pulled from routed clusters
|
||
max_docs = 64
|
||
# Score boost applied to medoid documents in routed clusters
|
||
medoid_boost = 0.05
|
||
# Maximum additive topology evidence applied during fusion
|
||
evidence_weight = 0.02
|
||
# Sparse/dense route score blend (0 = sparse only, 1 = dense only)
|
||
sparse_dense_alpha = 0.5
|
||
# Reject routes below this score
|
||
min_route_score = 0.0
|
||
# RRF k used by hybrid fusion
|
||
rrf_k = 12.0
|
||
# Cluster-route scoring rule for SparseGuidedClusterRouter.
|
||
# "current" — persistence + 0.5*cohesion + matchedSeed + memberCount/40 (default)
|
||
# "size_weighted" — current * 1/(1+log(size)); de-emphasizes giant clusters
|
||
# "seed_coverage" — rank by fraction of query seeds covered by each cluster
|
||
route_scoring = "current"
|
||
|
||
[topology]
|
||
# Cluster-formation engine used by the background topology rebuild.
|
||
# "connected" — reciprocal-edge connected components (default, baseline)
|
||
# "louvain" — modularity-greedy communities on the reciprocal-edge graph
|
||
# "kmeans" — embedding-space coarse quantizer
|
||
engine = "connected"
|
||
|
||
[topology.tuner]
|
||
# Phase G: per-corpus adaptive topology tuner (UCB1 multi-armed bandit over
|
||
# supported engines). Each successful rebuild produces an
|
||
# intrinsic-quality reward (singletonRatio, giantClusterRatio, gini, intraEdge);
|
||
# the bandit learns which arm fits the corpus shape best. No relevance labels
|
||
# required. Off by default.
|
||
#
|
||
# Tuning recipes — uncomment one block to activate, leaving the others as
|
||
# documentation. Enabling the tuner overrides the static engine above whenever
|
||
# an arm is pulled.
|
||
#
|
||
# off (default): static [topology] knobs win; bandit dormant.
|
||
enabled = false
|
||
#
|
||
# default: 10-min cooldown, 100-doc delta, plan-G reward weights.
|
||
# Best fit for steady-state corpora that grow modestly between rebuilds.
|
||
# enabled = true
|
||
# cooldown_minutes = 10
|
||
# doc_count_delta = 100
|
||
#
|
||
# aggressive: 30-min cooldown, 500-doc delta, lower singleton penalty.
|
||
# Best fit for fast-growing corpora where rebuilds are expensive (50k+ docs).
|
||
# enabled = true
|
||
# cooldown_minutes = 30
|
||
# doc_count_delta = 500
|
||
|
||
[topology.tuner.reward]
|
||
# Intrinsic-reward weights. Reward = clamp(1 - α·singleton - β·giant -
|
||
# γ·|gini-0.4| + δ·intraEdge, 0, 1). Defaults reflect the Phase G plan.
|
||
# Lowering alpha/beta accepts noisier clusterings; raising delta favors
|
||
# tighter intra-cluster cohesion at the cost of global structure.
|
||
alpha_singleton = 0.4
|
||
beta_giant_cluster = 0.4
|
||
gamma_gini_deviation = 0.1
|
||
delta_intra_edge = 0.1
|
||
|
||
[knowledge_graph]
|
||
# Database path for KG (relative to data_dir if not absolute)
|
||
# Defaults to {data_dir}/yams.db
|
||
db_path = "yams.db"
|
||
# Enable full-text search for aliases
|
||
enable_alias_fts = true
|
||
# Enable WAL mode
|
||
enable_wal = true
|
||
# Prefer exact alias matches
|
||
prefer_exact_alias_first = true
|
||
# Default query limit
|
||
default_limit = 1000
|
||
# Node cache capacity
|
||
node_cache_capacity = 10000
|
||
# Alias cache capacity
|
||
alias_cache_capacity = 50000
|
||
# Embedding cache capacity
|
||
embedding_cache_capacity = 10000
|
||
# Neighbor cache capacity
|
||
neighbor_cache_capacity = 10000
|
||
|
||
# External knowledge graph endpoints for taxonomy/ontology retrieval
|
||
endpoints = ["http://localhost:7200/repositories/yams"]
|
||
# Default taxonomy domains for classification
|
||
default_domains = ["computer_science", "business", "research"]
|
||
# Cache taxonomy for N minutes
|
||
taxonomy_cache_minutes = 60
|
||
# Maximum related concepts to fetch per query
|
||
max_related_concepts = 20
|
||
# Maximum concept relationship depth to explore
|
||
max_concept_depth = 2
|
||
# HTTP timeout for KG requests (milliseconds)
|
||
request_timeout_ms = 3000
|
||
# Enable automatic domain detection from document content
|
||
enable_domain_detection = true
|
||
# SPARQL endpoint authentication (if required)
|
||
auth_username = ""
|
||
auth_password = ""
|
||
# Enable concept relationship caching
|
||
enable_relationship_cache = true
|
||
# Relationship cache TTL (minutes)
|
||
relationship_cache_ttl_minutes = 120
|
||
|
||
[file_detection]
|
||
# Use libmagic if available
|
||
use_lib_magic = true
|
||
# Use built-in patterns
|
||
use_builtin_patterns = true
|
||
# Use custom patterns
|
||
use_custom_patterns = true
|
||
# Path to custom patterns file
|
||
patterns_file = ""
|
||
# Maximum bytes to read for detection
|
||
max_bytes_to_read = 512
|
||
# Cache detection results
|
||
cache_results = true
|
||
# Cache size
|
||
cache_size = 1000
|
||
|
||
[mcp_server]
|
||
# Enable MCP server
|
||
enable = false
|
||
# Transport: "stdio", "websocket"
|
||
transport = "stdio"
|
||
# WebSocket host
|
||
host = "localhost"
|
||
# WebSocket port
|
||
port = 8080
|
||
# WebSocket path
|
||
path = "/mcp"
|
||
# Use SSL/TLS
|
||
use_ssl = false
|
||
# Connection timeout (ms)
|
||
connect_timeout_ms = 5000
|
||
# Receive timeout (ms)
|
||
receive_timeout_ms = 30000
|
||
# Maximum message size
|
||
max_message_size = 1048576 # 1MB
|
||
# Enable WebSocket ping/pong
|
||
enable_ping_pong = true
|
||
# Ping interval (seconds)
|
||
ping_interval_s = 30
|
||
|
||
# Optional: directory for file-backed prompt templates (Markdown).
|
||
# Files named PROMPT-*.md will be exposed via `prompts/list` and `prompts/get`.
|
||
# Examples: PROMPT-search-codebase.md -> name: "search_codebase"
|
||
# If not set, defaults to XDG_DATA_HOME/yams/prompts or ~/.local/share/yams/prompts,
|
||
# and as a last resort uses ./docs/prompts when running from the repo root.
|
||
# prompts_dir = "/home/user/.local/share/yams/prompts"
|
||
|
||
[daemon.models]
|
||
# Maximum number of models to keep loaded in memory
|
||
max_loaded_models = 4
|
||
# Number of models to keep always loaded (hot pool)
|
||
hot_pool_size = 2
|
||
# Models to preload on daemon startup
|
||
preload_models = ["bart-large-mnli"]
|
||
# Load models only when first requested
|
||
lazy_loading = false
|
||
# Unload models after being idle for N seconds
|
||
model_idle_timeout_s = 300
|
||
# Enable GPU acceleration if available
|
||
enable_gpu = false
|
||
# Number of threads for ONNX inference
|
||
num_threads = 4
|
||
# Model eviction policy: "lru" (least recently used), "lfu", "fifo"
|
||
eviction_policy = "lru"
|
||
|
||
[daemon.resource_pool]
|
||
# Minimum ONNX sessions per model
|
||
min_sessions = 1
|
||
# Maximum ONNX sessions per model
|
||
max_sessions = 3
|
||
# Session idle timeout in seconds
|
||
idle_timeout_s = 300
|
||
# Validate session health before use
|
||
validate_on_acquire = true
|
||
|
||
[classification]
|
||
# Enable BART-based document classification for intelligent tagging
|
||
enable = false
|
||
# Path to BART-MNLI model
|
||
model_path = "~/.yams/models/bart-large-mnli"
|
||
# Confidence threshold for tag assignment
|
||
confidence_threshold = 0.7
|
||
# Maximum tags per document
|
||
max_tags_per_document = 5
|
||
# Maximum sequence length for classification
|
||
max_sequence_length = 1024
|
||
# Enable batch processing for efficiency
|
||
enable_batch_processing = true
|
||
# Batch size for classification
|
||
batch_size = 16
|
||
# Model inference timeout (milliseconds)
|
||
inference_timeout_ms = 5000
|
||
# Automatically classify documents during indexing
|
||
auto_classify_on_index = true
|
||
# Enable real-time classification during search
|
||
enable_search_time_classification = false
|
||
|
||
[search.hotzones]
|
||
# Enable hotzone-based result boosting
|
||
enable = false
|
||
# Decay factor for hotzone relevance over time (0.0-1.0)
|
||
decay_factor = 0.95
|
||
# Minimum access frequency to maintain hotzone
|
||
min_frequency = 3
|
||
# Hotzone decay interval (hours)
|
||
decay_interval_hours = 24
|
||
# Maximum boost factor for hot concepts
|
||
max_boost_factor = 2.0
|
||
# Enable persistence of hotzone data across restarts
|
||
enable_persistence = true
|
||
# Hotzone data file path (relative to data_dir if not absolute)
|
||
data_file = "hotzones.db"
|
||
# Background decay processing interval (minutes)
|
||
decay_processing_interval_minutes = 60
|
||
# Enable cross-user hotzone sharing
|
||
enable_shared_hotzones = false
|
||
|
||
[search.enhanced]
|
||
# Enable enhanced search pipeline with classification and KG
|
||
enable = false
|
||
# Weight for BART classification scoring in final results
|
||
classification_weight = 0.15
|
||
# Weight for knowledge graph expansion in final results
|
||
kg_expansion_weight = 0.10
|
||
# Weight for hotzone boosting in final results
|
||
hotzone_weight = 0.05
|
||
# Enable cross-domain concept discovery
|
||
enable_cross_domain = true
|
||
# Maximum concepts for expansion per search result
|
||
max_expansion_concepts = 10
|
||
# Enable search result re-ranking based on concept similarity
|
||
enable_concept_reranking = true
|
||
# Timeout for enhanced search pipeline (milliseconds)
|
||
enhanced_search_timeout_ms = 2000
|
||
|
||
[migrations]
|
||
# Automatically migrate on version change
|
||
auto_migrate = true
|
||
# Create backup before migration
|
||
backup_before_migrate = true
|
||
# Migration log file path
|
||
migration_log_path = "migrations.log"
|
||
|
||
[indexing]
|
||
# PBI-040: Synchronous FTS5 indexing threshold
|
||
# When adding <= sync_threshold documents, perform FTS5 indexing synchronously
|
||
# instead of queueing to PostIngestQueue. This eliminates the 5-10s async delay
|
||
# for grep on small batches, making results immediately available.
|
||
# Set to 0 to always use async indexing (original behavior).
|
||
# Default: 10 files
|
||
sync_threshold = 10
|
||
|
||
[downloader]
|
||
# Default concurrency for parallel connections
|
||
default_concurrency = 4
|
||
# Default chunk size in bytes
|
||
default_chunk_size_bytes = 8388608
|
||
# Per-connection timeout in ms
|
||
default_timeout_ms = 60000
|
||
# Follow HTTP redirects
|
||
follow_redirects = true
|
||
# Enable resume using HTTP Range/If-Range
|
||
resume = true
|
||
# Global rate limit (bytes/sec, 0 = unlimited)
|
||
rate_limit_global_bps = 0
|
||
# Per-connection rate limit (bytes/sec, 0 = unlimited)
|
||
rate_limit_per_conn_bps = 0
|
||
# Retry/backoff policy
|
||
max_retry_attempts = 5
|
||
retry_backoff_ms = 500
|
||
retry_backoff_multiplier = 2.0
|
||
retry_max_backoff_ms = 15000
|
||
# Default checksum algorithm when provided
|
||
checksum_algo = "sha256"
|
||
# Temporary file extension for staging
|
||
temp_extension = ".part"
|
||
# Store directly into CAS by default; no user path writes unless export requested
|
||
store_only = true
|
||
# Maximum allowed file size in bytes (0 = unlimited)
|
||
max_file_bytes = 0
|
||
|
||
[downloader.tls]
|
||
# Verify TLS certificates (recommended)
|
||
verify = true
|
||
# Path to CA bundle (empty = system default)
|
||
ca_path = ""
|
||
|
||
[downloader.proxy]
|
||
# Proxy URL (e.g., http://user:pass@host:port) or empty
|
||
url = ""
|
||
|
||
[plugins.symbol_extraction]
|
||
# Enable Tree-sitter based symbol extraction plugins (runtime toggle)
|
||
enable = true
|
||
# Auto-download missing Tree-sitter grammar shared objects on first use
|
||
auto_download_grammars = true
|
||
# Optional: restrict languages processed by the symbol extractor plugin
|
||
# languages = ["cpp", "python", "c", "go", "rust", "js", "ts"]
|
||
# Optional: override grammar .so paths per language
|
||
# grammar_paths.cpp = "/usr/lib/libtree-sitter-cpp.so"
|
||
# grammar_paths.python = "/usr/lib/libtree-sitter-python.so"
|
||
|
||
[cli.streaming]
|
||
# Enable streaming for large payloads on CLI <-> daemon IPC
|
||
enable = true
|
||
# Switch to streaming when payload exceeds this many bytes
|
||
payload_threshold_bytes = 262144
|
||
# Switch to streaming when first-byte latency exceeds this many ms
|
||
ttfb_threshold_ms = 150
|
||
# Per-chunk size on the streaming transport
|
||
chunk_size_bytes = 65536
|
||
# Maximum number of in-flight chunks
|
||
max_inflight_chunks = 4
|
||
|
||
[cli.pool]
|
||
# CLI <-> daemon client pool sizing and timeouts
|
||
max_clients = 8
|
||
min_clients = 1
|
||
acquire_timeout_ms = 5000
|
||
# 0 = unbounded waiter queue
|
||
max_waiters = 0
|
||
fair_queue = true
|
||
health_check_interval_ms = 30000
|
||
health_check_timeout_ms = 500
|
||
reconnect_backoff_base_ms = 100
|
||
reconnect_backoff_max_ms = 5000
|
||
reconnect_backoff_jitter_pct = 0.2
|
||
|
||
[repair]
|
||
# Online repair of missing embeddings / corrupted chunks while serving traffic
|
||
enable_online_repair = false
|
||
max_repair_concurrency = 1
|
||
repair_backoff_ms = 250
|
||
max_retries = 3
|