* fix(release): repair package repo publish
Arch repo metadata and R2 uploads need to be reproducible from CI, with retry hardening for transient Cloudflare failures.
* fix(daemon): stop shutdown log storm
Init waiter must treat ShuttingDown as terminal so daemon shutdown tests do not flood Meson logs while the daemon is stopping.
* refactor(cli): delegate serve to MCP binary
Keep yams serve UX while removing MCP server linkage from yams-cli. The standalone MCP binary owns stdio serving and exits on stdin EOF.
* refactor(cli): move daemon path helpers
Keep CLI path resolution out of YamsDaemon so later link cuts can separate CLI and daemon internals. Full yams_daemon removal still needs a socket-only daemon-client split.
* refactor(daemon): split embedded client
* perf(search): add lean-guided benchmark gates
Add Lean topology/search models, ingestion ablation docs, and focused regression tests for topology and compression threshold behavior.
Extract search observability, keep benchmark-only ablation controls, and make retrieval quality benchmarks default to Simeon while preserving explicit ONNX opt-in.
* refactor(config): move daemon policies
* refactor(daemon): extract plugin runtime
* refactor(daemon): untangle service coordinators
Untangle CLI/MCP from daemon service coordinators and the daemon static lib.
- MetadataRepository uses a daemon-neutral tree-diff callback. The
GraphComponent wrapper moves to src/daemon/components/metadata_graph_bridge.cpp,
owned by the daemon library.
- WriteCoordinator moves to a dedicated build-only yams_write_coordinator
static lib. Drop ResourceGovernor coupling inside the writer loop; batch
sizing still respects config.maxBatchSize.
- AppContext gains enqueuePostIngest callback. ServiceManager wires it to
its own enqueuePostIngest; app services no longer call ServiceManager
directly.
- Embedding repair uses BulkIngestLease/BeginBulkIngestCallback instead of
concrete VectorIndexCoordinator::BulkScope. Daemon dispatchers provide a
lease factory backed by the real coordinator.
- CLI daemon_command uses config helpers instead of YamsDaemon::getXDGRuntimeDir.
- Remove explicit dependency('yams_daemon') from src/cli and tools/yams-mcp.
- Declare missing yams_extraction/yams_ingest deps on yams_app_services so
app services link cleanly without daemon.
Validated:
meson compile -C build/release -j4 yams-daemon yams-cli yams-mcp-server
ninja -C build/release -t commands tools/yams-cli/yams-cli tools/yams-mcp/yams-mcp-server | grep -c libyams_daemon.a -> 0
yams-cli --version, yams-mcp-server init, yams serve --help smoke tests
Size drop on macOS release: yams-cli 41M -> 32M, yams-mcp-server 37M -> 22M.
* fix(cli): keep stdin add local fallback
No embedded daemon now. When yams add - buffers stdin and daemon IPC is missing, store via local app services instead of failing socket_missing.
Validated:
meson compile -C build/debug -j4 yams-cli catch2_cli_commands
MESON_BUILD_ROOT=/Users/trevon/work/tools/yams/build/debug build/debug/tests/catch2_cli_commands 'AddCommand - reads from piped stdin and stores content'
MESON_BUILD_ROOT=/Users/trevon/work/tools/yams/build/debug build/debug/tests/catch2_cli_commands
meson compile -C build/release -j4 yams-cli yams-mcp-server
meson compile -C build/asan-api -j2 yams-cli catch2_cli_commands
MESON_BUILD_ROOT=/Users/trevon/work/tools/yams/build/asan-api ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 build/asan-api/tests/catch2_cli_commands 'AddCommand - reads from piped stdin and stores content'
ninja -C build/release -t commands tools/yams-cli/yams-cli tools/yams-mcp/yams-mcp-server | grep libyams_daemon.a -> no output
* feat(bench): add xplan multi-arm experiment harness
Unified plan runner, ablation axes, REPORT/ablation docs, and
KPI snapshot so optimization loops stop living in shell matrices.
* feat(formal): expand topology/search Lean contracts
Boundary models for search provenance, construction gates,
and cluster/route objectives so Lean guides correctness while
xplan ranks performance levers.
* feat(search,topology): construction purity + graph expansion path
Raise topology build defaults (min edge 0.25, max component 64) and
split oversized CC pieces so hybrid assist is quality-positive on
scifact. Add GraphNeighbors expansion with medoid-anchor fallback,
structured helpers instead of nested session logic, and BEIR-default
xplan plans. Search engine extraction (fanout/classic pipeline) rides
along as the integration surface for routing.
* feat(topology): add KMeans engine and SGC identity contracts
Register kmeans in the factory with deterministic spherical k-means
over embeddings, and enforce SGC document-identity invariants in
debug builds with matching unit coverage.
* feat(daemon): topology readiness gates and selectable reranker
Drive topologyReady from published epoch/freshness/rebuild/dirty
ingest state (not just KG drain), surface those fields in search
stats, and wire onnx|simeon|auto|none cross-reranker selection.
* chore(search): drop meta_path tuner knobs
Meta-path routing is gone; remove dead TunedParams fields and the
ConfigResolver test for [search.meta_path].
* feat(bench): add topology_purity_validate plan
Repeats=3 validation matrix for construction-purity winners vs
topo_off so MRR deltas can clear run-to-run noise.
* chore: format add_command and config include order
Mechanical clang-format / include reorder only; no behavior change.
* feat(bench): decision-grade xplan loop for search engine
Document search-engine measurement in AGENTS; harden xplan with
repeats=3 plans, quality×latency primaries, mechanism metrics from
debug.jsonl, multi-rep log promotion, and archive superseded topology
plans.
* feat(graph): denser product semantic_neighbor topK
Raise default YAMS_GRAPH_SEMANTIC_TOPK fallback from 4 to 8 so product
graphs leave fewer degree-0 docs for GraphNeighbors expansion.
* feat(search): extract topology assist and cross-rerank seams
Pull topology assist into search_topology_stage (seed merge, skip
reasons, optional vector seed probe default 0). Extract cross_rerank
compute from search_engine. Wire probe via typed config/ConfigResolver.
* feat(bench): product-path search engine ablation plans
Add topology-off component, vector-weight, and tiered-execution xplan
plans (repeats=3) and wire them into the AGENTS measurement loop table.
* fix(ci): repair pre-push fallbacks
* feat(bench): lock-free mid-run builds + multi-corpus gates
xplan skips meson rebuild when the quality binary exists (flock +
YAMS_BENCH_FORCE_BUILD override) to stop multi-arm link races. Add
graph_vector weight and nfcorpus transfer-gate plans; document in AGENTS.
* fix(daemon): keep SearchEngine alive via shared_ptr cache
getCachedEngine previously published a raw pointer that metrics polling
used through rebuild, racing destructor of SearchEngine::Impl (TSAN).
Store and return a shared_ptr snapshot so diagnostic readers pin the
engine for the duration of getConfig/health checks.
Also adds the cautious vectorWeight 0.30→0.20 multi-corpus xplan plan.
* feat(search): route vectors through cached topology
Build and reuse validated topology snapshots, rank routed members by query similarity, and narrow the vector leg to the accepted document set with explicit work diagnostics.
Remove the retired HDBSCAN engine and vendor dependency, preserve typed topology policy through search tuning, and cover the runtime/configuration contracts.
* feat(bench): consolidate search decision plans
Enforce deterministic experiment identity and declared baselines, expose routed/global vector work metrics, and register the focused benchmark contracts.
Promote the compact repeats=3 routing-budget gate, archive superseded topology mechanism screens, and add multi-corpus product calibration plans.
* feat(search): refine topology vector routing
* fix(search): propagate daemon readiness
* feat(bench): measure generalized memory health
* fix(cli): honor in-process fallbacks
* ci: harden smolvm debug builds
* perf(search): route topology through filtered ANN
* feat(bench): measure read-write pressure
* perf(metadata): index symbol lookups on read pool
* fix(daemon): isolate startup reads and maintenance
* feat(bench): replay isolated generalized corpora
* feat(search): add evidence routing pipeline
Replace the blocking smolvm pre-push path with host ASan/TSan validation, harden sanitizer-sensitive smoke tests, and add recovery cleanup for malformed SQLite WAL sidecars.
* refactor(search): unify topology evidence path
Remove classic and sidecar fusion lanes so topology augments the recall-preserving ANN and lexical candidate pool through one product path.
* refactor(bench): prune superseded search lanes
Measure the topology-plus-ANN product path with stable experiment identity and remove obsolete sidecar and tiered controls.
* docs(search): retire stale experiment notes
Keep the benchmark handoff focused on the topology-plus-ANN product lane and its active decision plans.
* refactor(search): prune dead search surfaces
Remove unused fusion, reranker, policy, and router abstractions.
Bound topology materialization and keep document trace payloads opt-in.
* fix(cli): clear build warnings
* fix(xplan): reject stale run identity
* refactor(search)!: remove legacy query stack
Replace the unused AST/ranker/post-processor surface with focused facet aggregation used by product search.
BREAKING CHANGE: removes query parser, result ranker, search filter, and SearchResults container APIs from yams_search.
* refactor(search): type value stage traces
Remove synthetic ComponentResult markers for embedding and concept stages. Preserve failure and timeout states instead of overwriting them with fake successful results.
* refactor(search): isolate benchmark env overlays
Move test-only search environment parsing behind an injectable internal adapter. Keep all existing overlay keys and tuner pin semantics while restoring SearchEngineBuilder to composition.
* refactor(search): unify topology routing options
Snapshot topology policy once at the assist boundary and pass it through routing sessions and diagnostics. Remove repeated scalar copying without changing routing behavior or metric keys.
* fix(search): unify tuner config ownership
Use one complete config-to-params overlay for runtime seeding and no-tuner policy resolution. Reseed attached tuners on setConfig so reported and executed configuration cannot diverge.
* fix(search): snapshot tuner state per query
Read tuned config, params, and state under one lock before routing. Add a TSAN correlation test so adaptive observation cannot produce a torn logical query snapshot.
* fix(search): enforce topology routing contract
Generated configs must preserve hybrid-assist shadow routing, while daemon-backed search must abstain when published topology artifacts are stale. Keep standalone validation and global ANN recall intact.
* fix(daemon): let SQLite reclaim its file
Directly resizing a live database from sampled page counts can truncate pages allocated by concurrent writers. VACUUM must remain the only file-reclamation mechanism.
* fix(metadata): tolerate missing symbol FTS
Readiness lookups can race an unavailable optional FTS migration. Retain the indexed fast path, but retry against the base table when prepare or cached-statement execution proves the capability absent.
* build(fuzz): drop removed query parser target
The optional AFL build still referenced the deleted legacy query parser API and could no longer compile.
* fix(bench): include writes in drain oracle
A zero post-ingest queue is not durable drain while coordinated writes remain queued or in flight.
* fix(daemon): vacuum padded WAL databases safely
871 lines
29 KiB
TOML
871 lines
29 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
|
||
# Index type: "FLAT", "IVF_PQ", "HNSW"
|
||
index_type = "IVF_PQ"
|
||
# Number of partitions for IVF index
|
||
num_partitions = 256
|
||
# Number of sub-quantizers for PQ
|
||
num_sub_quantizers = 96
|
||
# 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"
|
||
# CLI <-> daemon client-pool worker threads
|
||
cli_pool_threads = 2
|
||
# 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
|
||
# aggressive_idle_shrink = false
|
||
# 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 passes (TurboQuant / 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
|
||
|
||
[daemon.client]
|
||
# Use daemon for embedding generation
|
||
use_daemon = true
|
||
# Fall back to local generation if daemon fails
|
||
fallback_to_local = true
|
||
# Maximum retry attempts
|
||
max_retries = 3
|
||
# Batch size for embedding requests
|
||
batch_size = 32
|
||
|
||
[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
|