Skip to main content

fxcp_core/
constants.rs

1// SPDX-License-Identifier: GPL-2.0-or-later
2// Copyright (C) 2025 Joel Wirāmu Pauling <aenertia@aenertia.net>
3//
4// fxcp-core/src/constants.rs  --  Shared constants for tuning, timeouts, thresholds
5
6//! Compile-time and runtime constants for foxing subsystems.
7//! Includes worker tuning, retry limits, buffer sizes, and feature flags.
8
9/// Crate version string, pulled from Cargo.toml at compile time.
10pub const VERSION: &str = env!("CARGO_PKG_VERSION");
11/// Git commit hash at build time, or "unknown" if not set.
12pub const GIT_COMMIT_HASH: &str = {
13    match option_env!("GIT_HEAD_REF") {
14        Some(s) => s,
15        None => "unknown",
16    }
17};
18/// Upper bound on worker threads the daemon will spawn.
19pub const MAX_WORKER_CORES: usize = 64;
20/// Default maximum event queue depth before back-pressure engages.
21pub const DEFAULT_QUEUE_MAX: usize = 500_000;
22/// Minimum interval between repeated error log messages for the same path.
23pub const ERROR_LIMITER_SECS: u64 = 5;
24/// Ceiling for exponential retry backoff across all retry loops.
25pub const MAX_RETRY_BACKOFF_SECS: u64 = 60;
26/// Free-space threshold on the target: below this, the daemon warns about low capacity.
27pub const CAPACITY_THRESHOLD_MB: u64 = 512;
28/// Default I/O buffer size for copy operations (MiB).
29pub const DEFAULT_IO_BUFFER_SIZE_MIB: u64 = 1;
30/// Seconds of inactivity before the daemon enters hibernation (reduced polling).
31pub const DEFAULT_HIBERNATION_SECS: u64 = 600;
32/// Polling interval (ms) for WAL barrier completion checks.
33pub const BARRIER_CHECK_INTERVAL: u64 = 50;
34/// Minimum I/O alignment for direct/O_DIRECT writes (bytes). Matches typical sector size.
35pub const MINIMUM_ALIGNMENT_BYTES: usize = 4096;
36/// Estimated per-entry memory overhead for the inode identity map (bytes).
37pub const DEFAULT_IDENTITY_MAP_OVERHEAD_BYTES: u64 = 4096;
38/// Per-event memory overhead in the dispatcher queue (bytes).
39pub const EVENT_QUEUE_OVERHEAD_BYTES: u64 = 256;
40/// Average total memory cost per queued event, including payload.
41pub const AVG_EVENT_OVERHEAD_BYTES: u64 = EVENT_QUEUE_OVERHEAD_BYTES + 128;
42/// Wire format version for BPF ring buffer event structs.
43pub const BPF_EVENT_VERSION: u8 = 5;
44/// Estimated number of in-flight entries in the BPF ring buffer.
45pub const ESTIMATED_RING_DEPTH: u64 = 4096;
46/// Maximum pending jobs in the hydration (resync) work queue.
47pub const HYDRATION_QUEUE_CAPACITY: usize = 10_000;
48/// Delay before retrying a hydration copy after an out-of-memory error.
49pub const HYDRATION_OOM_RETRY_DELAY_SECS: u64 = 5;
50/// Maximum retry attempts for a single hydration copy operation.
51pub const HYDRATION_COPY_MAX_ATTEMPTS: u32 = 10;
52/// Base delay for exponential backoff on hydration copy retries (ms).
53pub const HYDRATION_COPY_BACKOFF_BASE_MS: u64 = 100;
54/// Maximum backoff delay for hydration copy retries (ms).
55pub const HYDRATION_COPY_BACKOFF_MAX_MS: u64 = 5000;
56/// Maximum random jitter added to hydration copy backoff (ms).
57pub const HYDRATION_COPY_JITTER_MAX_MS: u64 = 100;
58/// Timeout for resolving an inode to a filesystem path during hydration.
59pub const HYDRATION_PATH_RESOLVE_TIMEOUT_SECS: u64 = 2;
60/// Polling interval when waiting for path resolution during hydration (ms).
61pub const HYDRATION_PATH_RESOLVE_POLL_MS: u64 = 100;
62/// Interval between hydration worker heartbeat log messages.
63pub const HYDRATION_HEARTBEAT_INTERVAL_SECS: u64 = 30;
64/// Timeout for receiving the next job from the hydration queue.
65pub const HYDRATION_JOB_RECV_TIMEOUT_SECS: u64 = 15;
66/// Minimum interval between memory allocation warning log messages during hydration.
67pub const HYDRATION_ALLOCATION_WARN_INTERVAL_SECS: u64 = 5;
68/// Directories modified within this window are considered "hot" and scanned first.
69pub const HYDRATION_HOT_DIR_THRESHOLD_SECS: u64 = 24 * 3600;
70/// Hydration batch limits for NVMe targets: (min_batch, max_batch).
71pub const HYDRATION_BATCH_LIMITS_NVME: (usize, usize) = (4096, 65536);
72/// Hydration batch limits for SSD targets: (min_batch, max_batch).
73pub const HYDRATION_BATCH_LIMITS_SSD: (usize, usize) = (2048, 32768);
74/// Hydration batch limits for network (NFS) targets: (min_batch, max_batch).
75pub const HYDRATION_BATCH_LIMITS_NETWORK: (usize, usize) = (1024, 16384);
76/// Hydration batch limits for HDD targets: (min_batch, max_batch).
77pub const HYDRATION_BATCH_LIMITS_HDD: (usize, usize) = (1024, 8192);
78/// Hydration batch limits for SD card targets: (min_batch, max_batch).
79pub const HYDRATION_BATCH_LIMITS_SDCARD: (usize, usize) = (128, 1024);
80/// Number of attempts to allocate a buffer from the worker pool before giving up.
81pub const WORKER_BUFFER_POOL_ALLOC_ATTEMPTS: usize = 5;
82/// Interval between worker housekeeping passes (stale entry cleanup, stats flush).
83pub const WORKER_CLEANUP_INTERVAL_SECS: u64 = 60;
84/// Minimum reorder buffer size before the worker starts processing events (bytes).
85pub const WORKER_REORDER_BUFFER_MIN_BYTES: usize = 16 * 1024;
86/// Maximum retries for a single event in the worker retry queue.
87pub const WORKER_RETRY_QUEUE_MAX_RETRIES: u32 = 10;
88/// Base backoff delay for the worker retry queue (ms). Doubles on each attempt.
89pub const WORKER_RETRY_QUEUE_BASE_BACKOFF_MS: u64 = 50;
90/// Delay after worker startup before running the first health check (ms).
91pub const WORKER_STARTUP_CHECK_DELAY_MS: u64 = 100;
92/// Minimum io_uring submission queue depth per worker.
93pub const WORKER_IO_URING_DEPTH_MIN: u32 = 4;
94
95/// Interval between adaptive tuner recalculations (microseconds).
96pub const WORKER_TUNE_INTERVAL_US: u64 = 50_000;
97/// Minimum events processed before the tuner considers adjusting parameters.
98pub const WORKER_TUNE_EVENT_THRESHOLD: usize = 10;
99/// Grace period after worker startup before I/O latency measurements are trusted.
100pub const WORKER_INITIAL_IO_LATENCY_SECS: u64 = 10;
101
102/// Debounce window for hydration tuner updates (microseconds).
103pub const TUNER_HYDRATION_DEBOUNCE_US: u64 = 50_000;
104
105/// Sliding window duration for tuner throughput and latency sampling.
106pub const TUNER_WINDOW_SECS: u64 = 3; 
107/// EWMA smoothing factor for tuner metrics (lower = smoother, slower to react).
108pub const TUNER_EWMA_ALPHA: f64 = 0.25; 
109
110/// Minimum delay between BBR tuner state transitions (microseconds).
111pub const TUNER_STATE_TRANSITION_DELAY_US: u64 = 500_000;
112
113/// Seconds of zero throughput before the tuner enters idle mode.
114pub const TUNER_IDLE_TIMEOUT_SECS: u64 = 30;
115/// Duration of the BBR startup phase (aggressive probing).
116pub const TUNER_STARTUP_DURATION_SECS: u64 = 2; 
117/// Maximum time the tuner stays in drain phase before returning to steady state.
118pub const TUNER_DRAIN_TIMEOUT_SECS: u64 = 6; 
119
120/// Upper bound on flush interval (microseconds). Caps how long writes can be batched.
121pub const TUNER_MAX_FLUSH_US: u64 = 5_000_000;
122/// Lower bound on flush interval (microseconds). Prevents excessive flushing.
123pub const TUNER_MIN_FLUSH_US: u64 = 50;
124/// BBR pacing gain during startup phase (2x = double estimated BDP).
125pub const TUNER_BDP_PACING_GAIN_STARTUP: f64 = 2.0;
126/// BBR pacing gain during drain phase (0.5x = half rate to clear queues).
127pub const TUNER_BDP_PACING_GAIN_DRAIN: f64 = 0.5;
128/// BBR pacing gain during bandwidth probing (1.25x = slight overshoot).
129pub const TUNER_BDP_PACING_GAIN_PROBE: f64 = 1.25;
130/// BBR pacing gain when muted by system pressure (0.75x = reduced throughput).
131pub const TUNER_BDP_PACING_GAIN_MUTED: f64 = 0.75;
132/// Memory usage fraction that triggers tuner throttling.
133pub const TUNER_MEMORY_PRESSURE_THRESHOLD: f64 = 0.90;
134/// I/O profile for HDD targets: (min_chunk, max_chunk, min_qd, max_qd).
135pub const PROFILE_HDD_VALUES: (u64, u64, usize, usize) = (2 * 1024 * 1024, 64 * 1024 * 1024, 4, 32);
136/// I/O profile for network (NFS) targets: (min_chunk, max_chunk, min_qd, max_qd).
137pub const PROFILE_NETWORK_VALUES: (u64, u64, usize, usize) = (1024 * 1024, 32 * 1024 * 1024, 8, 128);
138/// I/O profile for NVMe targets: (min_chunk, max_chunk, min_qd, max_qd).
139pub const PROFILE_NVME_VALUES: (u64, u64, usize, usize) = (256 * 1024, 16 * 1024 * 1024, 16, 1024);
140/// I/O profile for SSD targets: (min_chunk, max_chunk, min_qd, max_qd).
141pub const PROFILE_SSD_VALUES: (u64, u64, usize, usize) = (128 * 1024, 8 * 1024 * 1024, 8, 64);
142/// I/O profile for SD card targets: (min_chunk, max_chunk, min_qd, max_qd).
143pub const PROFILE_SDCARD_VALUES: (u64, u64, usize, usize) = (512 * 1024, 16 * 1024 * 1024, 1, 8);
144/// Cooldown period before the governor can toggle stress state again.
145pub const GOVERNOR_HYSTERESIS_SECS: u64 = 1;
146/// How often the governor samples PSI, memory, and CPU pressure (ms).
147pub const GOVERNOR_CHECK_INTERVAL_MS: u64 = 500;
148/// Initial pacing delay when the governor first detects system stress (ms).
149pub const GOVERNOR_PACING_INITIAL_MS: u64 = 10;
150/// Maximum pacing delay the governor can impose on workers (ms).
151pub const GOVERNOR_PACING_MAX_MS: u64 = 1000;
152/// Memory usage fraction above which the governor activates pressure throttling.
153pub const GOVERNOR_MEMORY_HIGH_WATERMARK_PCT: f64 = 0.90;
154/// Time-to-live for stale entries in the inode identity map (seconds).
155pub const IDENTITY_EVICTION_TTL_SECS: u64 = 12 * 3600;
156/// Number of events processed before capability caches are invalidated.
157pub const CACHE_TTL_EVENTS: u64 = 100_000;
158/// Interval between garbage collection sweeps for expired map entries.
159pub const GC_INTERVAL_SECS: u64 = 30;
160/// Maximum random jitter added to GC startup to avoid thundering herd (ms).
161pub const GC_STARTUP_JITTER_MAX_MS: u64 = 5000;
162/// Minimum quiet period between consecutive full-scan triggers.
163pub const FULL_SCAN_DEBOUNCE_SECS: u64 = 5;
164/// Minimum free inodes on the target before the daemon warns about exhaustion.
165pub const MIN_INODES_THRESHOLD: u64 = 1000;
166/// Smallest allowed chunk size in the buffer pool (bytes).
167pub const BUFFER_POOL_MIN_CHUNK_SIZE: usize = 4096;
168/// Copy failure rate (0.0..1.0) above which the governor declares the target unhealthy.
169pub const GOVERNOR_FAILURE_RATE_THRESHOLD: f64 = 0.5;
170/// Sliding window for computing the governor's failure rate.
171pub const GOVERNOR_FAILURE_WINDOW_SECS: u64 = 30;
172/// Timeout for copying small files (< 64KB). Covers metadata-heavy NFS round-trips.
173pub const COPY_TIMEOUT_SMALL_SECS: u64 = 120;
174/// Timeout for copying large files. Allows for slow network or HDD targets.
175pub const COPY_TIMEOUT_LARGE_SECS: u64 = 600;
176#[deprecated(note = "Use adaptive timeout from TunerOutput::postcopy_timeout_secs")]
177pub const POSTCOPY_TIMEOUT_SECS: u64 = 300;
178#[deprecated(note = "Use adaptive timeout from TunerOutput::segment_overall_timeout_secs")]
179pub const PROCESS_SEGMENT_TIMEOUT_SECS: u64 = 600;
180#[deprecated(note = "Use adaptive timeout from TunerOutput::segment_stall_timeout_secs")]
181pub const PROCESS_SEGMENT_STALL_SECS: u64 = 60;
182/// Consecutive io_uring completion timeouts before the worker declares a stall.
183pub const IOURING_COMPLETION_TIMEOUT_STREAK: usize = 600;
184/// Consecutive back-pressure timeouts before hydration gives up on a job.
185pub const HYDRATION_BACKPRESSURE_TIMEOUT_ATTEMPTS: usize = 120;
186/// How often the stall watchdog checks for stuck workers.
187pub const STALL_WATCHDOG_INTERVAL_SECS: u64 = 30;
188/// Seconds without progress before the watchdog declares a worker stalled.
189pub const STALL_WATCHDOG_THRESHOLD_SECS: u64 = 120;
190/// Retry queue iterations with zero progress before triggering a forced drain.
191pub const RETRY_QUEUE_STALL_THRESHOLD_ITERATIONS: usize = 20;
192/// PSI I/O pressure percentage that triggers governor throttling (normal mode).
193pub const GOVERNOR_PSI_IO_THRESHOLD_NORMAL: f64 = 10.0;
194/// PSI CPU pressure percentage that triggers governor throttling (normal mode).
195pub const GOVERNOR_PSI_CPU_THRESHOLD_NORMAL: f64 = 10.0;
196/// PSI I/O pressure threshold for hypervisor/container environments (relaxed mode).
197pub const GOVERNOR_PSI_IO_THRESHOLD_RELAXED: f64 = 50.0;
198/// PSI CPU pressure threshold for hypervisor/container environments (relaxed mode).
199pub const GOVERNOR_PSI_CPU_THRESHOLD_RELAXED: f64 = 50.0;
200/// When true, the daemon runs a single sync pass and exits (fxcp mode).
201pub static ONE_SHOT_MODE: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
202/// Minimum soft timeout for the reorder buffer before releasing out-of-order events (ms).
203pub const REORDER_SOFT_TIMEOUT_MIN_MS: u64 = 50;
204/// Maximum soft timeout for the reorder buffer (ms). Caps wait time for missing sequences.
205pub const REORDER_SOFT_TIMEOUT_MAX_MS: u64 = 500;
206/// Maximum number of events the reorder buffer can hold before dropping.
207pub const REORDER_BUFFER_CAPACITY: usize = 100_000;
208/// Time after which an undelivered reorder buffer entry is considered a zombie (ms).
209pub const REORDER_ZOMBIE_TIMEOUT_MS: u64 = 30_000;
210/// Reorder buffer fill fraction that triggers panic-mode forced delivery.
211pub const REORDER_PRESSURE_PANIC_PCT: f64 = 0.8;
212/// Reorder buffer fill fraction that triggers a warning log.
213pub const REORDER_PRESSURE_WARN_PCT: f64 = 0.5;
214/// Maximum memory budget for the reorder buffer (bytes).
215pub const REORDER_BUFFER_BYTES: u64 = 64 * 1024 * 1024;
216
217/// Timeout for the fsync liveness probe that detects stale NFS mounts.
218pub const MOUNT_PROBE_FSYNC_TIMEOUT_SECS: u64 = 5;
219/// Maximum events stored in the outage journal before oldest entries are dropped.
220pub const OUTAGE_JOURNAL_MAX_ENTRIES: usize = 100_000;
221/// Outage duration (seconds) beyond which recovery triggers a full scan instead of journal replay.
222pub const OUTAGE_FULL_SCAN_THRESHOLD_SECS: u64 = 86400;
223
224// --- Large File Resync (v0.9.2) ---
225/// Files above this threshold use the per-target Merkle index (.foxing_meta/merkle.db)
226/// instead of xattr storage, enabling finer-grained chunk sizes.
227pub const MERKLE_INDEX_THRESHOLD: u64 = 256 * 1024 * 1024; // 256MB
228/// Merkle chunk size for files stored in the per-target index.
229/// 512KB gives a practical tradeoff: 640KB index per 10GB file, 64MB per 1TB.
230pub const MERKLE_INDEX_CHUNK_SIZE: u64 = 512 * 1024; // 512KB
231/// Maximum serialized Merkle signature size that fits in a Linux xattr.
232pub const MERKLE_XATTR_MAX_BYTES: usize = 64 * 1024; // 64KB
233/// Minimum file size for the Merkle delta copy path in hydration.
234pub const MERKLE_DELTA_THRESHOLD: u64 = 1024 * 1024; // 1MB
235/// Minimum chunk size for Merkle tree (64KB). Adaptive chunk_size scales up for large files.
236pub const MIN_CHUNK_SIZE: usize = 65536;
237/// Max Merkle leaves that fit in a 64KB xattr with fat nodes.
238/// (65536 - 56 overhead) / 44 bytes per leaf (32 hash + 4 entropy + 8 simhash) = 1488.
239pub const MAX_LEAVES_PER_XATTR: u64 = 1488;
240/// Maximum dirty ranges tracked per file before overflow to full resync.
241pub const DIRTY_RANGE_MAX_PER_FILE: usize = 4096;
242
243// --- qcow2 Format Constants (spec-defined, not tunable) ---
244/// qcow2 magic bytes: "QFI\xfb" in big-endian.
245pub const QCOW2_MAGIC: u32 = 0x514649fb;
246/// Header extension type for persistent dirty bitmaps.
247pub const QCOW2_BITMAPS_EXTENSION: u32 = 0x23852875;
248/// Maximum backing file path length (qcow2 spec).
249pub const QCOW2_MAX_BACKING_PATH: u32 = 1023;
250/// qcow2 v3 header size (minimum).
251pub const QCOW2_HEADER_V3_SIZE: usize = 104;
252/// Dirty tracking bitmap type identifier.
253pub const QCOW2_BITMAP_TYPE_DIRTY: u8 = 1;
254/// Bitmap flag: in_use (inconsistent  --  was not properly synced).
255pub const QCOW2_BITMAP_FLAG_IN_USE: u32 = 0x01;
256/// Bitmap flag: auto (actively recording writes).
257pub const QCOW2_BITMAP_FLAG_AUTO: u32 = 0x02;
258/// L1/L2 host offset extraction mask (bits 9-55).
259pub const QCOW2_L2_OFFSET_MASK: u64 = 0x00FFFFFFFFFFFE00;
260
261/// How often workers check whether the target mount is still alive (ms).
262pub const WORKER_MOUNT_CHECK_INTERVAL_MS: u64 = 500;
263/// How often workers flush Prometheus metric gauges (ms).
264pub const WORKER_METRICS_UPDATE_INTERVAL_MS: u64 = 250;
265/// Small file threshold for hydration fast-path (skip io_uring overhead).
266pub const HYDRATION_SMALL_FILE_THRESHOLD: u64 = 256 * 1024; // 256KB
267/// Log progress every N directories during hydration scan.
268pub const HYDRATION_CHECKPOINT_INTERVAL: usize = 1000;
269/// Log progress every N files during hydration copy.
270pub const HYDRATION_LOG_INTERVAL: usize = 500;
271/// Storm detection threshold range for event burst detection.
272pub const STORM_THRESHOLD_MIN: usize = 2_000;
273/// Maximum rename storm threshold before forced drain.
274pub const STORM_THRESHOLD_MAX: usize = 100_000;
275
276// --- System Classification ---
277/// Systems with less than this are considered memory-constrained.
278pub const SYSTEM_MEMORY_CONSTRAINED_MB: u64 = 2048;
279/// Systems with more than this get expanded buffers.
280pub const SYSTEM_MEMORY_LARGE_MB: u64 = 16384;
281
282/// Sentinel value for unknown/unset inode generation.
283pub const GENERATION_UNKNOWN: u32 = u32::MAX;
284
285// --- Tuner v2 constants ---
286/// Default estimated bandwidth for new targets before probing (GB/s).
287pub const TUNER_DEFAULT_BANDWIDTH_GB_PER_SEC: f64 = 0.1;
288/// Default flush interval for worker event batches (microseconds).
289pub const TUNER_DEFAULT_FLUSH_INTERVAL_US: u64 = 1000;
290/// Default coalesce threshold for merging small writes (bytes).
291pub const TUNER_DEFAULT_COALESCE_BYTES: u64 = 65536;
292/// Maximum coalesce threshold (4MB)  --  memory guardrail.
293pub const TUNER_MAX_COALESCE_BYTES: u64 = 4_194_304;
294/// Default batch size for worker event processing.
295pub const TUNER_DEFAULT_BATCH_SIZE: usize = 32;
296/// Default io_uring submission queue depth.
297pub const TUNER_DEFAULT_QUEUE_DEPTH: u64 = 8;
298/// Default assumed average event payload size (bytes).
299pub const TUNER_DEFAULT_AVG_EVENT_SIZE_BYTES: u64 = 4096;
300/// Latency spike detection threshold (microseconds); exceeding triggers drain.
301pub const TUNER_DEFAULT_LATENCY_SPIKE_THRESHOLD_US: u64 = 5000;
302/// Minimum flush interval floor (microseconds).
303pub const TUNER_DEFAULT_FLUSH_MIN_US: u64 = 50;
304/// Maximum flush interval ceiling (microseconds).
305pub const TUNER_DEFAULT_FLUSH_MAX_US: u64 = 5_000_000;
306/// Minimum pending queue depth before back-pressure engages.
307pub const TUNER_DEFAULT_PENDING_QUEUE_MIN: usize = 16;
308/// Maximum pending queue depth before events are dropped.
309pub const TUNER_DEFAULT_PENDING_QUEUE_MAX: usize = 4096;
310/// Memory pressure percentage threshold for tuner v2 throttling.
311pub const TUNER_DEFAULT_MEMORY_PRESSURE_PCT: f64 = 0.85;
312/// EWMA smoothing factor for queue depth estimation.
313pub const TUNER_DEFAULT_QUEUE_DEPTH_ALPHA: f64 = 0.3;
314/// AIMD additive increase step for batch size growth.
315pub const TUNER_AIMD_ADDITIVE_STEP: usize = 4;
316/// AIMD multiplicative decrease factor on congestion detection.
317pub const TUNER_AIMD_MULTIPLICATIVE_FACTOR: f64 = 0.75;
318/// Bandwidth threshold above which aggressive probing is used (GB/s).
319pub const TUNER_HIGH_BANDWIDTH_THRESHOLD_GB_PER_SEC: f64 = 1.0;
320/// Hard upper bound on batch size regardless of tuner state.
321pub const TUNER_MAX_BATCH_SIZE: usize = 1024;
322/// Hard lower bound on batch size to prevent starvation.
323pub const TUNER_MIN_BATCH_SIZE: usize = 4;
324/// Default EWMA alpha for tuner v2 smoothing filters.
325pub const TUNER_V2_EWMA_ALPHA_DEFAULT: f64 = 0.25;
326
327// --- AI Content Routing Policy ---
328
329/// 100 MB  --  applies only to text/code files. Header-based groups
330/// (media, video, archive, binary, document) have no size limit.
331pub const AI_MAX_TEXT_FILE_SIZE: u64 = 100 * 1024 * 1024; // 100 MB
332
333/// Maximum bytes of text content to embed via chunking.
334/// Content beyond this point is truncated before `split_recursive()` to
335/// bound ORT embedding cost while still allowing large files to be indexed.
336/// 1 MiB of UTF-8 text produces ~4K chunks at 256 chars each.
337pub const AI_MAX_EMBED_BYTES: usize = 1_048_576; // 1 MiB
338
339// --- AI Chunk-Size Policy ---
340
341/// Chunk size for code files (chars). Smaller chunks preserve function boundaries.
342pub const AI_CHUNK_SIZE_CODE: usize = 256;
343/// Overlap for code chunks (chars).
344pub const AI_CHUNK_OVERLAP_CODE: usize = 32;
345
346/// Chunk size for text/prose files (chars). Larger to preserve paragraph context.
347pub const AI_CHUNK_SIZE_TEXT: usize = 1024;
348/// Overlap for text chunks (chars).
349pub const AI_CHUNK_OVERLAP_TEXT: usize = 128;
350
351/// Chunk size for markup files like HTML/XML (chars).
352pub const AI_CHUNK_SIZE_MARKUP: usize = 512;
353/// Overlap for markup chunks (chars).
354pub const AI_CHUNK_OVERLAP_MARKUP: usize = 128;
355
356/// Chunk size for document files like PDF/DOCX (chars). Large to preserve document structure.
357pub const AI_CHUNK_SIZE_DOCUMENT: usize = 1024;
358/// Overlap for document chunks (chars).
359pub const AI_CHUNK_OVERLAP_DOCUMENT: usize = 256;
360
361/// Default chunk size for unknown/unrecognized content (chars).
362pub const AI_CHUNK_SIZE_DEFAULT: usize = 512;
363/// Default overlap for unknown content (chars).
364pub const AI_CHUNK_OVERLAP_DEFAULT: usize = 64;
365
366// --- AI Enrichment Prompt Budget ---
367
368/// Maximum total prompt length (chars) sent to the LLM for enrichment.
369/// Metadata context (Magika, extracted metadata, similar files) is always
370/// included first. Raw file content fills the remaining budget.
371/// Default: 12000 chars (~=3000 tokens)  --  leaves headroom for LLM response
372/// within a 16K context window.
373pub const AI_MAX_PROMPT_CHARS: usize = 12_000;
374
375/// Maximum chars of raw file content in the enrichment prompt.
376/// This is the unstructured content budget AFTER metadata context.
377/// Truncated at UTF-8 boundary.  Default: 4000 chars.
378pub const AI_MAX_CONTENT_CHARS: usize = 4_000;
379
380/// Maximum chars for the indexed content preview section.
381/// Prevents large multi-chunk files from blowing out the prompt.
382/// Default: 1000 chars.
383pub const AI_MAX_PREVIEW_CHARS: usize = 1_000;
384
385/// Maximum chars for the collection context section.
386/// Default: 500 chars.
387pub const AI_MAX_COLLECTION_CONTEXT_CHARS: usize = 500;
388
389// --- Effort-Tiered Pipeline Defaults ---
390
391/// Maximum content chars sent to LLM at Quick effort.
392/// Quick skips LLM entirely, but if forced: minimal content.
393pub const AI_QUICK_MAX_CONTENT_CHARS: usize = 1_000;
394/// Maximum content chars at Balanced effort.
395pub const AI_BALANCED_MAX_CONTENT_CHARS: usize = 4_000;
396/// Maximum content chars at Deep effort.
397pub const AI_DEEP_MAX_CONTENT_CHARS: usize = 8_000;
398
399/// Fallback max prompt chars at Quick effort.
400pub const AI_QUICK_MAX_PROMPT_CHARS: usize = 4_000;
401/// Fallback max prompt chars at Balanced effort.
402pub const AI_BALANCED_MAX_PROMPT_CHARS: usize = 12_000;
403/// Fallback max prompt chars at Deep effort.
404pub const AI_DEEP_MAX_PROMPT_CHARS: usize = 50_000;
405
406/// Max preview chars at each effort level.
407pub const AI_QUICK_MAX_PREVIEW_CHARS: usize = 200;
408/// Max preview chars at Balanced effort.
409pub const AI_BALANCED_MAX_PREVIEW_CHARS: usize = 1_000;
410/// Max preview chars at Deep effort.
411pub const AI_DEEP_MAX_PREVIEW_CHARS: usize = 2_000;
412
413/// Archive peek budget (milliseconds) per effort level.
414pub const AI_QUICK_ARCHIVE_PEEK_BUDGET_MS: u64 = 10;
415/// Archive peek budget at Balanced effort.
416pub const AI_BALANCED_ARCHIVE_PEEK_BUDGET_MS: u64 = 10;
417/// Archive peek budget at Deep effort (0 = no budget cap).
418pub const AI_DEEP_ARCHIVE_PEEK_BUDGET_MS: u64 = 0;
419
420// --- RAG / Sidecar Discovery Constants ---
421// From docs/adrs/RAG-Standards-Sidecar-ADR.md
422
423/// Minimum Magika confidence to accept ORT-layer sidecar data without LLM review.
424/// At >=0.85, ORT alone can make the accept/reject decision.
425pub const AI_SIDECAR_HIGH_CONFIDENCE: f32 = 0.85;
426
427/// Minimum confidence to pass sidecar data to the LLM layer for evaluation.
428/// LLM can reason about borderline cases; below this threshold, discard.
429pub const AI_SIDECAR_CONFIDENCE_THRESHOLD: f32 = 0.70;
430
431/// Maximum chars of sidecar context injected into the enrichment prompt.
432pub const AI_MAX_SIDECAR_CONTEXT_CHARS: usize = 2_000;
433
434/// Maximum number of sidecar sources attached per file enrichment.
435pub const AI_SIDECAR_MAX_SOURCES_PER_FILE: usize = 3;
436
437/// Staleness penalty ratio: sidecar data older than Nx the file's own mtime
438/// delta gets a confidence penalty applied during sidecar scoring.
439pub const AI_SIDECAR_STALENESS_PENALTY_RATIO: f32 = 10.0;
440
441/// Adoption threshold: if fewer than 30% of files in a collection have a given
442/// sidecar format, treat it as low-adoption and apply stricter confidence gating.
443pub const AI_SIDECAR_LOW_ADOPTION_THRESHOLD: f32 = 0.30;
444
445/// Character budget for the sidecar type prefix in an enrichment prompt.
446pub const SIDECAR_PREFIX_BUDGET: usize = 100;
447
448/// ORT-layer confidence threshold for reference file injection.
449/// At >=0.90, reference file context can be injected without LLM gating.
450pub const AI_REFERENCE_ORT_THRESHOLD: f32 = 0.90;
451
452/// LLM-layer confidence threshold for reference file injection.
453pub const AI_REFERENCE_LLM_THRESHOLD: f32 = 0.75;
454
455/// Maximum chars of reference file context injected per enrichment prompt.
456pub const AI_MAX_REFERENCE_CONTEXT_CHARS: usize = 500;
457
458/// Maximum chars of association context (Dublin Core descriptions from associated files)
459/// injected into the enrichment prompt. Truncated at UTF-8 boundary.
460pub const AI_MAX_ASSOCIATION_CONTEXT_CHARS: usize = 1_000;
461
462// --- AI Magika Routing Confidence ---
463
464/// Magika ML confidence threshold for full trust (ignore extension).
465/// At or above this, Magika's label/group/is_text are used directly.
466pub const AI_MAGIKA_HIGH_CONFIDENCE: f32 = 0.85;
467
468/// Magika ML confidence threshold for extension-supplemented routing.
469/// Between this and AI_MAGIKA_HIGH_CONFIDENCE, Magika is used but
470/// extension info supplements when there's a conflict.
471/// Below this threshold, fall back to extension-only classification.
472pub const AI_MAGIKA_SUPPLEMENT_THRESHOLD: f32 = 0.50;
473
474/// Default Magika ML confidence threshold for the confidence gate in
475/// `MagikaRouter::classify_file()` and `media_meta::extract_metadata()`.
476/// At or above this score, Magika's classification is trusted directly.
477/// Below this score, the gate checks whether the file extension is in
478/// `MAGIKA_KNOWN_EXTENSIONS`: if yes, trust Magika; if no, fall back
479/// to extension-based `ContentRouter`.
480/// Configurable via `[ai.enrichment] magika_confidence_threshold` in
481/// foxingd config.  CLI `fxcp enrich` uses this constant as the default.
482pub const AI_MAGIKA_CONFIDENCE_THRESHOLD: f32 = 0.50;
483
484// --- AI Sandwich Sampling ---
485
486/// Head section ratio for sandwich sampling (35% of budget).
487pub const AI_SANDWICH_HEAD_RATIO: f64 = 0.35;
488/// Middle section ratio for sandwich sampling (25% of budget).
489pub const AI_SANDWICH_MID_RATIO: f64 = 0.25;
490/// Tail section ratio for sandwich sampling (20% of budget).
491pub const AI_SANDWICH_TAIL_RATIO: f64 = 0.20;
492/// Random sample ratio for sandwich sampling (20% of budget).
493pub const AI_SANDWICH_RANDOM_RATIO: f64 = 0.20;
494/// Number of random sample windows extracted from the interior.
495pub const AI_SANDWICH_RANDOM_WINDOWS: usize = 3;
496/// Marker prefix for the head section in sandwich output.
497pub const AI_SANDWICH_MARKER_HEAD: &str = "[HEAD]";
498/// Marker prefix for the middle section in sandwich output.
499pub const AI_SANDWICH_MARKER_MID: &str = "[MID]";
500/// Marker prefix for the tail section in sandwich output.
501pub const AI_SANDWICH_MARKER_TAIL: &str = "[TAIL]";
502/// Marker prefix for random sample sections in sandwich output.
503pub const AI_SANDWICH_MARKER_SAMPLE: &str = "[SAMPLE]";
504/// Maximum byte overhead from section markers and newlines.
505pub const AI_SANDWICH_MARKER_OVERHEAD: usize = 50;
506
507// -- Sprint 11b: Extension collision handling --
508/// Confidence multiplier for extensions in COLLISION_MAP table.
509/// Effective threshold = AI_MAGIKA_CONFIDENCE_THRESHOLD * AI_COLLISION_CONFIDENCE_MULTIPLIER.
510/// At defaults: 0.50 * 1.5 = 0.75 effective threshold for collision-prone extensions.
511/// This matches Magika's own raised threshold for markdown (0.75 in config.min.json).
512pub const AI_COLLISION_CONFIDENCE_MULTIPLIER: f32 = 1.5;
513
514/// Pico-8 cartridge PNG width (steganographic game data embedded in pixels).
515pub const AI_PICO8_PNG_WIDTH: u32 = 160;
516/// Pico-8 cartridge PNG height.
517pub const AI_PICO8_PNG_HEIGHT: u32 = 205;
518
519// Sprint 13 — extracted from inline literals
520
521/// Maximum number of keywords extracted per file in LLM enrichment output.
522pub const AI_MAX_KEYWORDS_PER_FILE: usize = 10;
523
524/// Maximum number of entity mentions extracted per file in LLM enrichment output.
525pub const AI_MAX_MENTIONS_PER_FILE: usize = 10;
526
527/// Minimum retry delay for LLM API calls in milliseconds (floor for exponential backoff).
528pub const AI_LLM_RETRY_MIN_DELAY_MS: u64 = 100;
529
530/// Confidence score assigned to files detected as Pico-8 cartridges via dimension probe.
531pub const AI_PICO8_DETECTION_CONFIDENCE: f32 = 0.80;
532
533/// Maximum effective confidence after collision gate adjustment (ceiling to avoid 1.0).
534pub const AI_COLLISION_CONFIDENCE_MAX: f32 = 0.99;
535
536/// Maximum line length for key-value pairs in raw sidecar parsing.
537pub const AI_SIDECAR_KV_MAX_LINE_LEN: usize = 200;
538
539/// Depth penalty multiplier applied to XML sidecar confidence scores.
540pub const AI_SIDECAR_XML_DEPTH_PENALTY: f32 = 0.85;
541
542/// HTTP status codes that indicate a retryable LLM API error.
543pub const AI_LLM_RETRYABLE_STATUS_CODES: &[u16] = &[429, 500, 502, 503, 529];
544
545// --- AI Enrichment Engine Defaults ---
546
547/// Default max output tokens per LLM enrichment request.
548/// Applies when `ai.enrichment.max_tokens` is unset.
549pub const AI_LLM_DEFAULT_MAX_TOKENS: u32 = 512;
550
551/// Default sampling temperature for LLM enrichment requests.
552/// Low value (0.2) favours consistency over creativity.
553pub const AI_LLM_DEFAULT_TEMPERATURE: f32 = 0.2;
554
555/// Default daily token budget (input + output). 0 = unlimited.
556/// Offline-first default: local LLM servers (llama.cpp, vLLM, Ollama) have no token cost.
557/// Set to a non-zero value only for paid cloud APIs (e.g. 100_000 for OpenAI free tier).
558pub const AI_LLM_DAILY_TOKEN_BUDGET: u64 = 0;
559
560/// HTTP timeout per LLM enrichment request (seconds).
561pub const AI_LLM_REQUEST_TIMEOUT_SECS: u64 = 30;
562
563/// Maximum retries on transient LLM failures before giving up.
564pub const AI_LLM_MAX_RETRIES: u32 = 2;
565
566/// Maximum concurrent LLM enrichment requests.
567pub const AI_LLM_MAX_CONCURRENT: usize = 8;
568
569/// Initial backoff delay for LLM retry loop (milliseconds).
570pub const AI_LLM_RETRY_INITIAL_DELAY_MS: u64 = 500;
571
572/// Maximum backoff delay for LLM retry loop (milliseconds).
573pub const AI_LLM_RETRY_MAX_DELAY_MS: u64 = 30_000;
574
575/// Budget reset interval  --  tokens_used counter resets after this many seconds.
576pub const AI_LLM_BUDGET_RESET_SECS: u64 = 86_400;
577
578/// Truncation limit for dc_abstract when LLM returns non-JSON (chars).
579pub const AI_SAFE_TRUNCATE_ABSTRACT_LIMIT: usize = 200;
580
581/// Truncation limit for description when LLM returns non-JSON (chars).
582pub const AI_SAFE_TRUNCATE_DESCRIPTION_LIMIT: usize = 500;
583
584/// Truncation limit for sidecar context and extracted metadata in
585/// synthesised enrichment prompts (chars).
586pub const AI_SAFE_TRUNCATE_CONTEXT_LIMIT: usize = 300;
587
588// --- AI ORT / ONNX Embedding Engine ---
589
590/// Maximum input sequence length (tokens) for ORT/ONNX tokenizer.
591pub const AI_ORT_MAX_SEQUENCE_LENGTH: usize = 512;
592
593/// Default batch size for ORT embedding inference.
594pub const AI_ORT_DEFAULT_BATCH_SIZE: usize = 32;
595
596// --- AI pgvector Sync ---
597
598/// File batch size per transaction during pgvector export.
599pub const AI_PGVECTOR_FILE_BATCH_SIZE: usize = 500;
600
601/// HNSW `m` parameter  --  max bi-directional links per node.
602pub const AI_HNSW_M: u32 = 16;
603
604/// HNSW `ef_construction` for 64-bit SimHash binary index (bit_hamming_ops).
605/// Set to 256 per SOTA recommendation for binary vectors with high near-duplicate ratios
606/// (NapierOne dataset analysis: 64 produces poor recall on dense similarity clusters).
607pub const AI_HNSW_EF_CONSTRUCTION_SIMHASH: u32 = 256;
608
609/// HNSW `ef_construction` for embedding cosine-similarity index.
610pub const AI_HNSW_EF_CONSTRUCTION_COSINE: u32 = 128;
611
612// --- AI Docling Document Extraction ---
613
614/// Maximum wait time for async docling-serve conversion (seconds).
615pub const AI_DOCLING_TIMEOUT_SECS: u64 = 120;
616
617/// Poll interval for docling-serve async status checks (milliseconds).
618pub const AI_DOCLING_POLL_INTERVAL_MS: u64 = 1000;
619
620// --- Worker Event Processing ---
621
622/// Sequential I/O proximity threshold (bytes). I/O within this range of the
623/// last sequential offset is treated as sequential for scheduling purposes.
624pub const SEQUENTIAL_PROXIMITY_THRESHOLD_BYTES: u64 = 262_144;
625
626/// Emergency prune threshold (bytes). When target storage drops below this,
627/// the worker initiates emergency version pruning before retrying the copy.
628pub const EMERGENCY_PRUNE_THRESHOLD_BYTES: u64 = 1_073_741_824;
629
630/// Base timeout for copy operations (seconds). The actual timeout is computed
631/// as `base + (file_size / 10MB) * per_10mb`, capped at `COPY_TIMEOUT_CAP_SECS`.
632pub const COPY_TIMEOUT_BASE_SECS: u64 = 60;
633
634/// Additional timeout per 10 MB of file data (seconds).
635pub const COPY_TIMEOUT_PER_10MB_SECS: u64 = 60;
636
637/// Maximum copy timeout regardless of file size (seconds).
638pub const COPY_TIMEOUT_CAP_SECS: u64 = 300;
639
640/// Timeout for simple event handler operations: rename, truncate, fallocate (seconds).
641pub const EVENT_HANDLER_TIMEOUT_SECS: u64 = 60;
642
643/// Default Prometheus metrics port for the foxingd API server.
644pub const DEFAULT_METRICS_PORT: u16 = 9100;
645
646// --- BPF Event Pipeline ---
647
648/// Sequence gap threshold for BPF ring buffer. Gaps larger than this trigger
649/// panic-mode hydration and a synthetic SequenceGap event.
650pub const BPF_SEQUENCE_GAP_THRESHOLD: u64 = 1000;
651
652/// Consecutive target errors before the worker requests a rescan on recovery.
653pub const TARGET_ERROR_STREAK_THRESHOLD: u32 = 5;
654
655/// Maximum events drained from the coalescer per flush tick. Prevents
656/// unbounded processing in a single select iteration.
657pub const WORKER_FLUSH_CAP_PER_TICK: usize = 256;
658
659/// Maximum capacity of the per-worker write coalescer. Also used as the
660/// denominator for buffer utilization metrics.
661pub const COALESCER_MAX_CAPACITY: usize = 10_000;
662
663/// Maximum entries in the TransientFilter map before forced GC + eviction.
664/// Prevents unbounded HashMap growth under sustained create storms.
665pub const BPF_MAX_TRANSIENT_ENTRIES: usize = 100_000;
666
667/// Maximum number of block devices tracked simultaneously in the BPF
668/// sequence tracker and identity map.
669pub const BPF_MAX_TRACKED_DEVICES: usize = 256;
670
671/// TransientFilter GC cutoff (seconds). Entries older than this are evicted
672/// during periodic garbage collection to prevent unbounded growth.
673pub const BPF_TRANSIENT_GC_CUTOFF_SECS: u64 = 30;
674
675/// BPF ring buffer poll interval (milliseconds). Controls how often the
676/// userspace event loop polls the kernel ring buffer for new events.
677pub const BPF_RING_POLL_INTERVAL_MS: u64 = 100;
678
679/// Interval between BPF per-device statistics reports (seconds).
680pub const BPF_STATS_REPORT_INTERVAL_SECS: u64 = 30;
681
682/// Per-event fixed overhead estimate (bytes) used by the ReorderBuffer
683/// for memory accounting alongside the event payload size.
684pub const BPF_EVENT_OVERHEAD_BYTES: u64 = 64;
685
686/// Base event payload size estimate (bytes) used by the ReorderBuffer
687/// for memory accounting. The actual size adds the event name length.
688pub const BPF_EVENT_SIZE_ESTIMATE_BYTES: u64 = 256;
689
690/// Bounded frontier width limit for the Coalescer. When the batch exceeds
691/// this threshold, aggressive transient lifecycle pruning is triggered.
692pub const COALESCER_FRONTIER_WIDTH_LIMIT: usize = 10_000;
693
694/// Channel capacity for the metadata tin in the TinnedDispatcher.
695/// Metadata events (chmod, chown, xattr) are droppable under pressure.
696pub const DISPATCHER_METADATA_TIN_CAPACITY: usize = 1024;
697
698/// Channel capacity for the bulk tin in the TinnedDispatcher.
699/// Bulk events (write, truncate) are freely droppable; hydration catches misses.
700pub const DISPATCHER_BULK_TIN_CAPACITY: usize = 4096;
701
702// --- NFS Client Defaults ---
703
704/// TCP connect timeout for NFSv4.2 client session recovery and privileged port fallback.
705pub const NFS_TCP_CONNECT_TIMEOUT_SECS: u64 = 5;
706
707/// TCP read/write timeout for NFSv4.2 compound RPC streams.
708pub const NFS_TCP_RW_TIMEOUT_SECS: u64 = 10;
709
710/// Sleep duration between retries when the NFS server is in grace period.
711pub const NFS_RECONNECT_SLEEP_MS: u64 = 500;
712
713/// Default NFS server port (IANA-assigned for NFSv4).
714pub const NFS_DEFAULT_PORT: u16 = 2049;
715
716/// Timeout for the NFS NULL RPC liveness probe (connect + read + write).
717pub const NFS_PROBE_TIMEOUT_SECS: u64 = 2;
718
719/// Maximum NFSv4.2 request size for channel negotiation (16MB data + 4KB header).
720pub const NFS_MAX_REQUEST_SIZE: usize = 16 * 1024 * 1024 + 4096;
721
722/// Maximum NFSv4.2 response size for channel negotiation (1MB).
723pub const NFS_MAX_RESPONSE_SIZE: usize = 1024 * 1024;
724
725/// Maximum file data size for krb5p compound RPC bypass (bytes).
726///
727/// The kernel's gss_krb5_unwrap produces garbled output when priv_bytes
728/// (4-byte seq_num + compound_args) exceeds 3,952 bytes (247 x 16 AES blocks).
729/// With ~260 bytes of non-data compound overhead, this limits write data to ~3,688
730/// bytes. We use 3,584 (3.5KB) as a conservative threshold.
731///
732/// Files exceeding this are routed directly to VFS sendfile, avoiding the
733/// failed-compound + session-recovery penalty (~25ms per file).
734///
735/// Empirical: priv_bytes=3,952 -> NFS4_OK; priv_bytes=3,964 -> NFS4ERR_BAD_STATEID.
736/// GSS wrap overhead is constant at 72 bytes regardless of input size.
737/// AUTH_SYS compounds of the same size succeed without error.
738pub const KRB5P_MAX_WRITE_DATA: usize = 3584;
739
740/// GSS wrap token overhead per compound RPC (RFC 4121 S4.2.6.2).
741///
742/// Breakdown:
743/// - 16B: GSS token header (TOK_ID + Flags + Filler + EC + RR + SND_SEQ)
744/// - 16B: AES confounder (prepended to plaintext before encryption)
745/// - 12B: HMAC-SHA1-96 integrity check value
746/// - ~28B: XDR alignment padding and GSS framing overhead
747/// Total: ~72B per compound body
748///
749/// This overhead is already accounted for in KRB5P_MAX_WRITE_DATA (3584B),
750/// which is empirically derived to stay safely below the 3952B AES-CTS
751/// block boundary (247 x 16B AES blocks).
752pub const GSS_WRAP_OVERHEAD_BYTES: usize = 72;
753
754/// ALPN protocol identifier for RPC-over-TLS (RFC 9289 S7.2).
755pub const NFS_TLS_ALPN: &[u8] = b"sunrpc";
756
757/// Timeout for the TLS handshake after AUTH_TLS STARTTLS upgrade (seconds).
758pub const NFS_TLS_HANDSHAKE_TIMEOUT_SECS: u64 = 10;
759
760// --- I/O Operations ---
761
762/// Deadline for io_uring completion poll before giving up on a single wait cycle.
763pub const IO_URING_READABLE_TIMEOUT_MS: u64 = 100;
764
765/// Minimum interval between repeated log messages during io_uring stall detection.
766pub const LOG_THROTTLE_INTERVAL_SECS: u64 = 10;
767
768// --- Sync / Tree Walking ---
769
770/// Age cutoff for orphaned `.tmp.*` files during cleanup (seconds).
771/// Files older than this are considered abandoned and removed.
772pub const HOT_DIR_CUTOFF_SECS: u64 = 3600;
773
774// --- Filesystem Ioctl Magic Numbers ---
775
776/// FICLONE ioctl number for CoW reflink cloning.
777pub const FICLONE_IOCTL: u64 = 0x40049409;
778/// FS_IOC_SETFLAGS ioctl for setting filesystem flags (immutable, append-only).
779pub const FS_IOC_SETFLAGS_IOCTL: u64 = 0x40086602;
780/// XFS_IOC_EXCHANGE_RANGE ioctl for atomic file content exchange.
781pub const XFS_IOC_EXCHANGE_RANGE: u64 = 0xC0385828;
782/// btrfs filesystem magic number (from statfs).
783pub const BTRFS_SUPER_MAGIC: u64 = 0x9123683E;
784/// F2FS filesystem magic number (from statfs).
785pub const F2FS_SUPER_MAGIC: u64 = 0xF2F52010;
786
787// --- Content Verification ---
788
789/// Sample size for head/tail content verification (64KB).
790pub const CONTENT_VERIFY_SAMPLE_SIZE: usize = 65536;
791/// Minimum file size before tail sampling is used during content verification (128KB).
792pub const CONTENT_VERIFY_TAIL_THRESHOLD: usize = 131072;
793
794// --- I/O Size Thresholds ---
795
796/// Minimum hole size for FALLOC_FL_PUNCH_HOLE operations (16KB).
797pub const MIN_HOLE_PUNCH_SIZE: u64 = 16 * 1024;
798/// Headroom bytes reserved for FXAR restore disk space checks (10MB).
799pub const FXAR_RESTORE_HEADROOM_BYTES: u64 = 10 * 1024 * 1024;
800
801// --- Filesystem Geometry ---
802
803/// Standard disk sector size (bytes). Used for sparse file detection
804/// (`blocks * SECTOR_SIZE < file_size / 2`) and I/O alignment fallback.
805pub const SECTOR_SIZE_BYTES: u64 = 512;
806
807// --- copy_file_range ---
808
809/// Maximum chunk size per `copy_file_range(2)` call (1 GiB).
810/// Kernel may copy less; caller loops until complete.
811pub const COPY_FILE_RANGE_CHUNK_SIZE: u64 = 1024 * 1024 * 1024;
812
813// --- AI Preview / Truncation ---
814
815/// Default character limit for chunk content previews stored in
816/// `ChunkMeta`, pgvector `foxing_chunks.preview`, and SSE payloads.
817pub const AI_CHUNK_PREVIEW_CHARS: usize = 200;
818
819/// HNSW capacity growth increment when the index is full.
820pub const AI_HNSW_CAPACITY_GROWTH_INCREMENT: usize = 1000;
821
822// --- Daemon Housekeeping ---
823
824/// Interval between target mount health checks in the hydration manager (seconds).
825pub const MOUNT_HEALTH_CHECK_INTERVAL_SECS: u64 = 10;
826
827/// SSE event stream poll sleep when no new events are available (milliseconds).
828pub const SSE_POLL_INTERVAL_MS: u64 = 100;
829
830/// Maximum dirty-range journal file size before the journal is discarded
831/// and a full Merkle resync is triggered (bytes). 10 MiB.
832pub const DIRTY_JOURNAL_MAX_BYTES: u64 = 10 * 1024 * 1024;
833
834/// Batch buffer capacity for the hydration manager event loop.
835pub const HYDRATION_BATCH_BUFFER_CAPACITY: usize = 100;
836
837/// Minimum free bytes on target before fxcp sync aborts with an error (10 MiB).
838pub const SYNC_MIN_FREE_BYTES: u64 = 10 * 1024 * 1024;
839
840/// SMB/CIFS filesystem magic number (from statfs).
841pub const SMB_SUPER_MAGIC: i64 = 0x517B;
842/// CIFS filesystem magic number (from statfs).
843pub const CIFS_MAGIC_NUMBER: i64 = 0xFF534D42_u32 as i64;
844
845/// Hydration timeout floors for Network/NFS targets: (stall_secs, overall_secs, postcopy_secs).
846pub const HYDRATION_TIMEOUT_FLOOR_NETWORK: (u64, u64, u64) = (60, 600, 300);
847/// Hydration timeout floors for HDD targets: (stall_secs, overall_secs, postcopy_secs).
848pub const HYDRATION_TIMEOUT_FLOOR_HDD: (u64, u64, u64) = (30, 300, 120);
849/// Hydration timeout floors for SSD targets: (stall_secs, overall_secs, postcopy_secs).
850pub const HYDRATION_TIMEOUT_FLOOR_SSD: (u64, u64, u64) = (15, 120, 60);
851/// Hydration timeout floors for unknown/default targets: (stall_secs, overall_secs, postcopy_secs).
852pub const HYDRATION_TIMEOUT_FLOOR_DEFAULT: (u64, u64, u64) = (10, 60, 30);
853
854// --- FUSE Accelerator ---
855
856/// Default metadata cache TTL (seconds) for the FUSE passthrough overlay.
857/// StorageClassification-aware overrides apply at runtime: NFS 30s, HDD 60s, NVMe 5s.
858/// Corresponds to `fuse_cache_ttl_secs` in `TargetConfig`.
859pub const FUSE_CACHE_TTL_DEFAULT_SECS: u64 = 30;
860
861// --- Fsync Latency Tracking ---
862
863/// Default average fsync latency estimate for `FsyncLatencyTracker` (microseconds).
864/// Corresponds to 1 second  --  conservative initial estimate for cold starts.
865pub const FSYNC_LATENCY_DEFAULT_AVG_US: u64 = 1_000_000;
866
867/// Default fsync latency deviation for `FsyncLatencyTracker` (microseconds).
868/// Used in adaptive timeout calculation: timeout = avg + 4 x deviation.
869pub const FSYNC_LATENCY_DEFAULT_DEVIATION_US: u64 = 500_000;
870
871/// Maximum fsync latency estimate after timeout doubling (microseconds).
872/// Caps `record_timeout()` to prevent runaway growth (30 seconds).
873pub const FSYNC_LATENCY_MAX_US: u64 = 30_000_000;
874
875/// Minimum adaptive fsync timeout (microseconds). Floor for `get_timeout()` clamp (5 seconds).
876pub const FSYNC_TIMEOUT_MIN_US: u64 = 5_000_000;
877
878/// Maximum adaptive fsync timeout (microseconds). Ceiling for `get_timeout()` clamp (60 seconds).
879pub const FSYNC_TIMEOUT_MAX_US: u64 = 60_000_000;
880
881// --- I/O Copy Strategy ---
882
883/// Per-call chunk size for `sendfile(2)` in the copy-file helper (2 MiB).
884/// Prevents a single sendfile from monopolizing the kernel for too long.
885pub const SENDFILE_CHUNK_SIZE: u64 = 2 * 1024 * 1024;
886
887/// Minimum file size to activate the NFS sendfile fast-path (64 KiB).
888/// Below this, io_uring overhead is negligible and sendfile adds no benefit.
889pub const NFS_SENDFILE_MIN_SIZE: u64 = 65_536;
890
891/// File size boundary for copy strategy selection (64 KiB).
892/// Files smaller than this use sendfile; larger files use io_uring pipeline.
893pub const SMALL_FILE_THRESHOLD: u64 = 64 * 1024;
894
895/// Read chunk size for stdin pipe mode (1 MiB).
896/// Balances memory usage against syscall frequency for piped input.
897pub const STDIN_CHUNK_SIZE: usize = 1024 * 1024;
898
899/// Minimum page-cache residency ratio to trigger the cachestat sendfile fast-path.
900/// At >=80% resident, sendfile outperforms io_uring for files in the decision zone.
901pub const CACHE_RESIDENCY_SENDFILE_THRESHOLD: f64 = 0.80;
902
903// --- Hashing ---
904
905/// Default file-size threshold for lite (head+tail) hashing (128 KiB).
906/// Files smaller than this get a full BLAKE3 hash; larger files use a
907/// head+tail 4 KiB sample for fast change detection.
908pub const LITE_HASH_DEFAULT_THRESHOLD: u64 = 128 * 1024;
909
910/// Minimum file size for parallel BLAKE3 hashing via `update_rayon()` (1 MiB).
911/// Below this threshold, single-threaded hashing is faster due to rayon overhead.
912pub const RAYON_HASH_THRESHOLD: u64 = 1_048_576;
913
914// --- NFS Client Extended ---
915
916/// Maximum compound RPC byte budget before splitting into a new compound (800 KiB).
917/// Keeps each compound well within the server's `ca_maxrequestsize` (~16 MiB).
918pub const NFS_COMPOUND_BYTE_LIMIT: usize = 800 * 1024;
919
920/// Estimated XDR header overhead per compound RPC (bytes).
921/// Covers SEQUENCE, PUTFH root, and framing. Used as the initial byte accumulator.
922pub const NFS_XDR_HEADER_OVERHEAD: usize = 512;
923
924/// Estimated per-operation XDR overhead (bytes). Covers PUTFH + OPEN + WRITE +
925/// CLOSE op headers and filehandle encoding for each file in a compound.
926pub const NFS_XDR_PER_OP_OVERHEAD: usize = 256;
927
928/// Requested `ca_maxoperations` in CREATE_SESSION. The server negotiates down
929/// to its actual limit; this is the client's opening bid.
930pub const NFS_CA_MAX_OPERATIONS: u32 = 64;
931
932/// Initial `max_files_per_compound` for `CompoundSizeTuner` before AIMD adaptation.
933pub const NFS_COMPOUND_TUNER_INITIAL_MAX_OPS: u32 = 64;
934
935/// Start of the privileged port range for NFS source-port binding.
936/// NFS servers with `sec=sys` may require connections from ports < 1024.
937pub const NFS_PRIVILEGED_PORT_START: u16 = 900;
938
939/// End (exclusive) of the privileged port range for NFS source-port binding.
940pub const NFS_PRIVILEGED_PORT_END: u16 = 1024;
941
942/// Initial capacity for the RPC reply buffer `Vec<u8>`.
943/// Sized to hold a typical small-compound response without reallocation.
944pub const NFS_REPLY_INITIAL_CAPACITY: usize = 4096;
945
946/// IANA-assigned NFS/RDMA port (RFC 8267).
947pub const NFS_RDMA_PORT: u16 = 20049;
948
949// --- RDMA Transport ---
950
951/// Maximum inline NFS body size for RDMA Send/Recv operations (bytes).
952/// Must fit within `RDMA_MAX_INLINE` = body + header + padding.
953pub const RDMA_MAX_INLINE_BODY: usize = 4096;
954
955/// Padding/overhead added to inline body for RDMA message framing (bytes).
956pub const RDMA_INLINE_PADDING: usize = 64;
957
958/// Completion queue depth for RDMA ibverbs CQ creation.
959pub const RDMA_CQ_DEPTH: i32 = 16;
960
961/// Timeout for RDMA CM address/route resolution (milliseconds).
962pub const RDMA_RESOLVE_TIMEOUT_MS: i32 = 5000;
963
964/// Maximum CQ poll spins before declaring an RPC timeout.
965/// At ~10ns per spin, 10M spins ~= 100ms busy-wait ceiling.
966pub const RDMA_CQ_POLL_MAX_SPINS: u64 = 10_000_000;
967
968/// Fallback RPC timeout for RDMA operations (seconds).
969/// Used when CQ polling exhausts `RDMA_CQ_POLL_MAX_SPINS` without completion.
970pub const RDMA_RPC_TIMEOUT_SECS: u64 = 30;
971
972// --- Governor Extended ---
973
974/// PSI relaxation multiplier for hypervisor/container environments.
975/// Hypervisor-reported PSI values are inflated by host contention;
976/// this multiplier relaxes the threshold to avoid false throttling.
977pub const GOVERNOR_HYPERVISOR_PSI_MULTIPLIER: f64 = 5.0;
978
979/// Total operations before the governor auto-resets its failure window.
980/// Prevents transient error bursts from permanently marking a target unhealthy.
981pub const GOVERNOR_FAILURE_WINDOW_RESET_OPS: u64 = 1000;
982
983// --- WAL (Write-Ahead Log) ---
984
985/// Initial token count for WAL batch admission control.
986/// Each write operation consumes a token; tokens regenerate on flush.
987pub const WAL_BATCH_TOKENS_INITIAL: usize = 1000;
988
989/// Maximum concurrent writers before the WAL engages barrier mode.
990/// Beyond this threshold, new writers block until the current batch completes.
991pub const WAL_MAX_WRITERS_BEFORE_BARRIER: usize = 10;
992
993/// Sequence number proximity to `u64::MAX` that triggers an overflow reset.
994/// When `global_seq >= u64::MAX - threshold`, the sequence resets to 1.
995pub const WAL_SEQUENCE_OVERFLOW_THRESHOLD: u64 = 10_000;
996
997// --- Sync / Progress Reporting ---
998
999/// Progress reporting interval in JSON output mode (milliseconds).
1000pub const PROGRESS_INTERVAL_JSON_MS: u64 = 1000;
1001
1002/// Progress reporting interval in human-readable output mode (milliseconds).
1003pub const PROGRESS_INTERVAL_HUMAN_MS: u64 = 200;
1004
1005/// io_uring submission queue depth for fxcp CLI tree-copy operations.
1006pub const FXCP_IO_URING_SQ_DEPTH: u32 = 256;
1007
1008/// Buffer pool count for fxcp CLI tree-copy io_uring pipeline.
1009pub const FXCP_BUFFER_POOL_COUNT: usize = 64;
1010
1011// --- NFS Writer / BatchTuner ---
1012
1013/// Channel capacity for the NFS writer task's job queue.
1014/// Workers submit `NfsWriteJob` entries; the writer drains in batch cycles.
1015pub const NFS_WRITER_CHANNEL_CAPACITY: usize = 1000;
1016
1017/// Maximum files per compound RPC for RDMA transport.
1018/// RDMA_MAX_INLINE=4188B  --  multi-file compounds exceed inline capacity.
1019pub const NFS_RDMA_MAX_BATCH: usize = 1;
1020
1021/// Maximum compound byte budget for RDMA transport (bytes).
1022/// Sized to fit within RDMA_MAX_INLINE (4188B) with header overhead.
1023pub const NFS_RDMA_MAX_BATCH_BYTES: usize = 3500;
1024
1025/// Maximum files per compound RPC for krb5p transport.
1026/// Reduced to avoid accumulating large batches that serialize into
1027/// many single-file compounds wastefully under AES encryption.
1028pub const NFS_KRB5P_MAX_BATCH: usize = 2;
1029
1030/// Maximum files per compound RPC for TCP/TLS AUTH_SYS transport.
1031pub const NFS_TCP_MAX_BATCH: usize = 200;
1032
1033/// Maximum compound byte budget for TCP/TLS transport (8 MiB).
1034pub const NFS_TCP_MAX_BATCH_BYTES: usize = 8 * 1024 * 1024;
1035
1036/// EWMA smoothing factor for BatchTuner queue depth and RTT tracking.
1037pub const NFS_BATCH_EWMA_ALPHA: f64 = 0.2;
1038
1039/// Queue pressure ratio above which BatchTuner increases batch size.
1040pub const NFS_BATCH_PRESSURE_HIGH: f64 = 0.8;
1041
1042/// Queue pressure ratio below which BatchTuner decreases batch size.
1043pub const NFS_BATCH_PRESSURE_LOW: f64 = 0.2;
1044
1045/// Additive increase step for BatchTuner AIMD batch size growth.
1046pub const NFS_BATCH_ADDITIVE_INCREASE: usize = 5;
1047
1048/// Multiplicative decrease factor for BatchTuner AIMD batch size reduction.
1049pub const NFS_BATCH_MULTIPLICATIVE_DECREASE: f64 = 0.75;
1050
1051/// Max files per batch_read_head compound (SEQUENCE+PUTFH+[LOOKUP+READ]×N).
1052/// Conservative for 8KB data responses (24KB reply per compound).
1053pub const NFS_BATCH_READ_HEAD_FILES_PER_COMPOUND: usize = 3;
1054
1055// --- Daemon Lifecycle ---
1056
1057/// Grace period for worker tasks to complete during daemon shutdown (seconds).
1058pub const SHUTDOWN_DEADLINE_SECS: u64 = 10;
1059
1060/// TCP listen backlog for the Prometheus/API server socket.
1061pub const API_LISTEN_BACKLOG: u32 = 128;
1062
1063/// Channel capacity for TUI event and command channels.
1064pub const TUI_CHANNEL_CAPACITY: usize = 32;
1065
1066/// Epoch offset for full-scan debounce: `last_full_scan` is initialized to
1067/// `now - offset` so the first health-check-triggered scan fires immediately.
1068pub const FULL_SCAN_EPOCH_OFFSET_SECS: u64 = 60;
1069
1070/// Timeout for workers to acknowledge a drain barrier during recovery (seconds).
1071pub const DRAIN_ACK_TIMEOUT_SECS: u64 = 30;
1072
1073/// Timeout for a targeted recovery scan to complete (seconds).
1074pub const RECOVERY_SCAN_TIMEOUT_SECS: u64 = 120;
1075
1076// --- SSE / EventBus ---
1077
1078/// Maximum entries pulled from the EventBus per SSE poll cycle.
1079pub const SSE_PULL_BATCH_SIZE: usize = 64;
1080
1081/// Interval between SSE keepalive comments to prevent proxy/client timeouts (seconds).
1082pub const SSE_KEEPALIVE_INTERVAL_SECS: u64 = 15;
1083
1084/// Broadcast channel capacity for EventBus change notifications.
1085pub const EVENTBUS_NOTIFY_CHANNEL_CAPACITY: usize = 64;
1086
1087// --- Stratis Integration ---
1088
1089/// Stratis pool free-space percentage that triggers critical warnings and
1090/// emergency version pruning to reclaim capacity.
1091pub const STRATIS_POOL_CRITICAL_PCT: f64 = 5.0;
1092
1093/// Stratis pool free-space percentage that triggers low-space warnings.
1094pub const STRATIS_POOL_LOW_PCT: f64 = 10.0;
1095
1096/// Interval between Stratis pool capacity checks via D-Bus (seconds).
1097pub const STRATIS_MONITOR_INTERVAL_SECS: u64 = 30;
1098
1099// --- AI Sidecar Confidence ---
1100
1101/// Confidence score for raw/unstructured sidecar fallback matches.
1102pub const AI_SIDECAR_RAW_CONFIDENCE: f32 = 0.15;
1103
1104/// Confidence score for structured key-value sidecar matches.
1105pub const AI_SIDECAR_KV_CONFIDENCE: f32 = 0.60;
1106
1107/// Confidence score for XML-structured sidecar matches (highest structural signal).
1108pub const AI_SIDECAR_XML_CONFIDENCE: f32 = 0.95;
1109
1110/// Confidence score for exact filename-stem sidecar matches.
1111pub const AI_SIDECAR_EXACT_CONFIDENCE: f32 = 0.85;
1112
1113/// Jaro-Winkler similarity threshold for fuzzy sidecar filename matching.
1114pub const AI_SIDECAR_FUZZY_THRESHOLD: f32 = 0.80;
1115
1116/// Confidence multiplier applied to Jaro-Winkler score for fuzzy sidecar matches.
1117pub const AI_SIDECAR_FUZZY_CONFIDENCE_MULTIPLIER: f32 = 0.70;
1118
1119// --- AI Media Association ---
1120
1121/// Confidence score for exact stem-match media-to-parent file association.
1122pub const AI_MEDIA_ASSOC_EXACT_CONFIDENCE: f32 = 0.92;
1123
1124/// Jaro-Winkler similarity threshold for fuzzy media file association.
1125pub const AI_MEDIA_ASSOC_FUZZY_THRESHOLD: f32 = 0.85;
1126
1127/// Confidence multiplier for fuzzy media file association scores.
1128pub const AI_MEDIA_ASSOC_FUZZY_CONFIDENCE_MULTIPLIER: f32 = 0.85;
1129
1130// --- AI Search / Embedding ---
1131
1132/// Reciprocal Rank Fusion (RRF) parameter `k` for hybrid search scoring.
1133/// Higher k smooths rank differences; k=60 is the standard default (Cormack et al.).
1134pub const AI_RRF_K: f64 = 60.0;
1135
1136/// Approximate characters-per-token ratio for LLM token budget estimation.
1137/// Used to convert available token budget into a character limit for content truncation.
1138pub const AI_TOKENS_TO_CHARS_RATIO: f64 = 3.5;
1139
1140/// Default embedding vector dimensions used when the model path is unknown or empty (HTTP-only mode).
1141///
1142/// **v0.10.0-dev reference value: 768** — set to match the production endpoint used during
1143/// 0.10-dev development: Granite Embedding 278M multilingual on awa:8001 (768-dim vectors).
1144///
1145/// Operators using a different model MUST set this to match their endpoint:
1146///   - Granite Embedding 278M / nomic-embed-text / BGE-base → 768
1147///   - all-MiniLM-L6-v2 / BGE-small / GTE-small → 384
1148///   - stella_en_400M / jina-embeddings-v3 → 1024
1149///
1150/// Mismatch between this constant and the actual endpoint causes EmbeddingIndex (local usearch HNSW)
1151/// to initialize with the wrong dimension, silently producing incorrect similarity scores.
1152/// The HTTP embedding engine auto-detects dimensions from the endpoint probe and is unaffected,
1153/// but the local HNSW index uses this constant as its fixed dimension at creation time.
1154///
1155/// Value 768 matches the Granite Embedding 278M production endpoint (awa:8001) used in v0.10.0-dev.
1156/// Operators using a different model (e.g. all-MiniLM-L6-v2 at 384-dim) must ensure their model
1157/// path is recognized by `fxcp-ai/src/model_registry.rs` so the correct dimension is returned.
1158pub const AI_DEFAULT_EMBEDDING_DIMS: usize = 768;
1159
1160/// Maximum ORT intra-op parallelism threads. Caps thread count to avoid
1161/// over-subscribing CPU cores on high-core-count machines.
1162pub const AI_ORT_MAX_INTRA_THREADS: usize = 8;
1163
1164// --- Hydration Worker ---
1165
1166/// io_uring ring size per hydration worker.
1167/// Caps memory usage (e.g. 32 x 4MB = 128MB per worker instead of unbounded).
1168pub const HYDRATION_RING_BUFFER_CAP: u64 = 32;
1169
1170/// Buffer count when optimal allocation fails (16 x 4MB = 64MB).
1171pub const HYDRATION_FALLBACK_BUFFER_COUNT: usize = 16;
1172
1173/// Fallback chunk size in bytes when optimal allocation fails (4 MiB).
1174pub const HYDRATION_FALLBACK_CHUNK_SIZE: usize = 4 * 1024 * 1024;
1175
1176/// Buffer pool capacity divisor when entering yield mode.
1177pub const HYDRATION_YIELD_MODE_BUFFER_DIVISOR: usize = 5;
1178
1179/// Multiplier applied to `global_buffer_limit` to derive the storm threshold.
1180pub const HYDRATION_STORM_THRESHOLD_MULTIPLIER: u64 = 20;
1181
1182/// Hysteresis multiplier for transitioning from primary -> yield mode.
1183pub const HYDRATION_HYSTERESIS_UP: f64 = 1.1;
1184
1185/// Hysteresis multiplier for transitioning from yield -> primary mode.
1186pub const HYDRATION_HYSTERESIS_DOWN: f64 = 0.9;
1187
1188/// Fraction of global buffer budget allocated to hydration in yield mode.
1189pub const HYDRATION_MEMORY_SHARE_YIELD: f64 = 0.20;
1190
1191/// Fraction of global buffer budget allocated to hydration in primary mode.
1192pub const HYDRATION_MEMORY_SHARE_PRIMARY: f64 = 0.70;
1193
1194/// Retry iterations during backpressure stall before aborting scan.
1195pub const HYDRATION_BACKPRESSURE_SLEEP_ITERATIONS: usize = 5;
1196
1197/// Sleep between backpressure stall retries (milliseconds).
1198pub const HYDRATION_BACKPRESSURE_SLEEP_MS: u64 = 100;
1199
1200/// Sleep at low watermark during scan (milliseconds).
1201pub const HYDRATION_LOW_WATERMARK_SLEEP_MS: u64 = 20;
1202
1203/// Extra ring slots added beyond buffers_per_ring for safety margin.
1204pub const HYDRATION_IOURING_RING_PADDING: usize = 8;
1205
1206/// Interval between allocation rechecks in hydration worker loop (seconds).
1207pub const HYDRATION_ALLOC_RECHECK_INTERVAL_SECS: u64 = 5;
1208
1209/// Log worker liveness every N processed jobs.
1210pub const HYDRATION_WORKER_LOG_INTERVAL: u64 = 100;
1211
1212/// io_uring ring size for dirty-range replay operations.
1213pub const HYDRATION_DIRTY_RANGE_RING_SIZE: u32 = 64;
1214
1215/// Bytes to read for head-hash content verification in hydration sync_file_needed.
1216/// 8KB covers the observed corruption pattern (zeros starting at byte 2).
1217pub const HYDRATION_HEAD_VERIFY_BYTES: usize = 8192;
1218
1219// --- Daemon Orchestration ---
1220
1221/// Maximum targets tracked by TuningBoardManager.
1222pub const TUNING_BOARD_MANAGER_CAPACITY: usize = 64;
1223
1224/// Minimum entries in the identity map after clamping.
1225pub const IDENTITY_MAP_MIN_ENTRIES: usize = 10_000;
1226
1227/// Maximum entries in the identity map after clamping.
1228pub const IDENTITY_MAP_MAX_ENTRIES: usize = 1_000_000;
1229
1230/// LRU size divisor: lru_size = max_entries / this.
1231pub const IDENTITY_LRU_SIZE_DIVISOR: usize = 10;
1232
1233/// SystemGovernor periodic update interval (seconds).
1234pub const SYSTEM_GOVERNOR_UPDATE_INTERVAL_SECS: u64 = 5;
1235
1236/// TuningBoardManager global consensus interval (seconds).
1237pub const TUNING_BOARD_CONSENSUS_INTERVAL_SECS: u64 = 5;
1238
1239/// Broadcast channel capacity for barrier coordination.
1240pub const BARRIER_BROADCAST_CHANNEL_CAPACITY: usize = 16;
1241
1242/// NFS client pool session count.
1243pub const NFS_CLIENT_POOL_SIZE: usize = 4;
1244
1245/// Emergency pressure threshold for AI enrichment skip.
1246pub const GOVERNOR_EMERGENCY_PRESSURE_THRESHOLD: f64 = 0.9;
1247
1248/// Throttle pressure threshold for AI enrichment delay.
1249pub const GOVERNOR_THROTTLE_PRESSURE_THRESHOLD: f64 = 0.5;
1250
1251// --- Daemon Lifecycle ---
1252
1253/// HTTP probe timeout for `is_daemon_running` liveness check (seconds).
1254pub const DAEMON_PROBE_TIMEOUT_SECS: u64 = 2;
1255
1256/// Remote monitor poll interval for status/metrics fetching (milliseconds).
1257pub const MONITOR_POLL_INTERVAL_MS: u64 = 500;
1258
1259/// Maximum versions shown in `snapshot list` output.
1260pub const VERSION_LIST_DISPLAY_LIMIT: usize = 20;
1261
1262/// Timeout waiting for BPF probes to attach at daemon startup (seconds).
1263pub const BPF_READY_TIMEOUT_SECS: u64 = 60;
1264
1265/// One-shot sync mode hydration completion check interval (milliseconds).
1266pub const ONE_SHOT_CHECK_INTERVAL_MS: u64 = 500;
1267
1268// --- BPF Dedup ---
1269
1270/// Dedup window for kprobe/fentry/LSM duplicate events (milliseconds).
1271pub const BPF_DEDUP_WINDOW_MS: u64 = 5;
1272
1273/// How many dedup windows to retain before evicting (cleanup keeps Nx window).
1274pub const BPF_DEDUP_RETAIN_FACTOR: u32 = 10;
1275
1276/// Periodic cleanup interval for the dedup cache (every N events).
1277pub const BPF_DEDUP_CLEANUP_INTERVAL: u64 = 1000;
1278
1279// --- Reorder / Coalescer Thresholds ---
1280
1281/// Pending event count that triggers panic-mode forced delivery in ReorderBuffer.
1282pub const REORDER_PENDING_PANIC_COUNT: usize = 1000;
1283
1284/// Pending event count that triggers warning-level stall timeout in ReorderBuffer.
1285pub const REORDER_PENDING_WARN_COUNT: usize = 100;
1286
1287/// Stall timeout under pressure conditions in ReorderBuffer (milliseconds).
1288pub const REORDER_PRESSURE_STALL_TIMEOUT_MS: u64 = 10;
1289
1290/// Initial Vec capacity for EventBatch in the Coalescer.
1291pub const COALESCER_BATCH_INITIAL_CAPACITY: usize = 128;
1292
1293// --- AI Sidecar Discovery ---
1294
1295/// Minimum files in a directory before sidecar detection activates.
1296pub const AI_SIDECAR_MIN_DIR_FILES: usize = 3;
1297
1298/// Minimum fraction (0.0–1.0) of files sharing the dominant extension before
1299/// `format_directory_context()` emits a directory context string.
1300/// Below this threshold the directory is too heterogeneous — context would be
1301/// misleading noise rather than useful signal for the LLM.
1302/// Example: 10 files, 3 .gg + 2 .zip + 2 .png + 3 others → dominant = 30% → suppressed.
1303///          100 files, 85 .smc + 10 .txt + 5 .xml → dominant = 85% → emitted.
1304pub const AI_DIR_CONTEXT_MIN_DOMINANT_FRACTION: f64 = 0.50;
1305
1306/// Raw fallback snippet truncation (chars).
1307pub const AI_SIDECAR_RAW_SNIPPET_CHARS: usize = 500;
1308
1309/// XML match snippet truncation (chars).
1310pub const AI_SIDECAR_XML_SNIPPET_CHARS: usize = 1000;
1311
1312/// Minimum KV-style lines to classify a sidecar as structured.
1313pub const AI_SIDECAR_KV_MIN_LINES: usize = 3;
1314
1315/// Maximum KV-style lines to extract from a structured sidecar.
1316pub const AI_SIDECAR_KV_MAX_LINES: usize = 10;
1317
1318/// Context lines before an exact filename-stem match.
1319pub const AI_SIDECAR_EXACT_CONTEXT_BEFORE: usize = 5;
1320
1321/// Context lines after an exact filename-stem match (i + N).
1322pub const AI_SIDECAR_EXACT_CONTEXT_AFTER: usize = 6;
1323
1324/// Exact match snippet truncation (chars).
1325pub const AI_SIDECAR_EXACT_SNIPPET_CHARS: usize = 800;
1326
1327/// Context lines before a fuzzy filename-stem match.
1328pub const AI_SIDECAR_FUZZY_CONTEXT_BEFORE: usize = 3;
1329
1330/// Context lines after a fuzzy filename-stem match (idx + N).
1331pub const AI_SIDECAR_FUZZY_CONTEXT_AFTER: usize = 4;
1332
1333/// Fuzzy match snippet truncation (chars).
1334pub const AI_SIDECAR_FUZZY_SNIPPET_CHARS: usize = 600;
1335
1336/// Maximum ancestor directory depth for gamelist.xml walk-up discovery.
1337pub const AI_SIDECAR_ANCESTOR_MAX_DEPTH: usize = 4;
1338
1339// --- AI Enrichment Extended ---
1340
1341/// Hard cap on prompt chars for deep effort with probed context (chars).
1342pub const AI_DEEP_MAX_PROMPT_CHARS_CAP: usize = 200_000;
1343
1344/// RPM sliding window duration for LLM rate limiting (seconds).
1345pub const AI_LLM_RPM_WINDOW_SECS: u64 = 60;
1346
1347/// Maximum multiplier for exponential backoff on empty AI sweeps.
1348/// When a periodic sweep finds zero files needing work, the interval doubles
1349/// (up to base_interval × this cap). Resets to base on any non-empty sweep.
1350pub const AI_SWEEP_MAX_BACKOFF_MULTIPLIER: u32 = 8;
1351
1352// --- AI pgvector Reconnect ---
1353
1354/// Base interval for pgvector reconnection attempts when initial connection fails (seconds).
1355pub const AI_PGVECTOR_RECONNECT_BASE_SECS: u64 = 60;
1356
1357/// Maximum interval for pgvector reconnection with exponential backoff cap (seconds).
1358pub const AI_PGVECTOR_RECONNECT_MAX_SECS: u64 = 300;
1359
1360/// Minimum cosine similarity for taxonomy_nearest() pgvector HNSW fallback to populate PipelineContext.
1361pub const AI_TAXONOMY_NEAREST_THRESHOLD: f32 = 0.70;
1362
1363/// CID pull-through mode: accept enrichment only when stored effort >= requested effort.
1364pub const AI_PGVECTOR_PULL_MODE_OPPORTUNISTIC: &str = "opportunistic";
1365
1366/// CID pull-through mode: accept any enrichment for matched CIDs, never call LLM.
1367pub const AI_PGVECTOR_PULL_MODE_AUTHORITATIVE: &str = "authoritative";
1368
1369// --- AI pgvector Sync Extended ---
1370
1371/// Default maximum pgvector queue depth before back-pressure.
1372pub const AI_PGVECTOR_MAX_QUEUE_DEPTH: usize = 10_000;
1373
1374/// Default flush batch size for pgvector sync.
1375pub const AI_PGVECTOR_FLUSH_BATCH_SIZE: usize = 5000;
1376
1377/// SQL parameter limit chunk size for pgvector batch inserts.
1378pub const AI_PGVECTOR_CHUNK_SUB_BATCH: usize = 1000;
1379
1380/// Maximum chunk content previews returned per file from pgvector.
1381pub const AI_PGVECTOR_MAX_CHUNK_PREVIEWS: usize = 20;
1382
1383// --- AI Binary Extraction ---
1384
1385/// Hard deadline for binary metadata extraction (milliseconds).
1386pub const AI_BINARY_DEADLINE_MS: u64 = 10;
1387
1388/// Maximum printable strings to extract from binary `.rodata`/`.rdata`.
1389pub const AI_BINARY_MAX_STRINGS: usize = 50;
1390
1391/// Minimum string length for binary string extraction.
1392pub const AI_BINARY_MIN_STRING_LEN: usize = 5;
1393
1394/// Maximum symbols (imports + exports) before truncating.
1395pub const AI_BINARY_MAX_SYMBOLS: usize = 100;
1396
1397/// Bytes of entry-point code to disassemble via capstone.
1398pub const AI_BINARY_CAPSTONE_PEEK_BYTES: usize = 256;
1399
1400// --- AI Container RAG ---
1401
1402/// Maximum requires entries displayed in container sidecar context.
1403pub const AI_CONTAINER_MAX_REQUIRES_DISPLAY: usize = 10;
1404
1405/// Maximum file entries displayed in container sidecar context.
1406pub const AI_CONTAINER_MAX_FILES_DISPLAY: usize = 15;
1407
1408/// Maximum requires to extract from RPM metadata.
1409pub const AI_CONTAINER_MAX_REQUIRES: usize = 20;
1410
1411/// Maximum file entries to extract from RPM metadata.
1412pub const AI_CONTAINER_MAX_FILE_ENTRIES: usize = 20;
1413
1414/// Maximum OCI manifest layers to extract.
1415pub const AI_CONTAINER_MAX_OCI_LAYERS: usize = 10;
1416
1417// --- Identity / Watch ---
1418
1419/// Yield to scheduler every N entries during identity scan.
1420pub const IDENTITY_SCAN_YIELD_INTERVAL: usize = 100;
1421
1422/// Sleep every N entries during identity scan for throttling.
1423pub const IDENTITY_SCAN_SLEEP_INTERVAL: usize = 1000;
1424
1425/// Sleep duration during identity scan throttling (microseconds).
1426pub const IDENTITY_SCAN_SLEEP_US: u64 = 50;
1427
1428// --- TUI ---
1429
1430/// Bandwidth history ring buffer capacity for TUI sparkline.
1431pub const TUI_BANDWIDTH_HISTORY_CAPACITY: usize = 60;
1432
1433/// Latency history ring buffer capacity for TUI sparkline.
1434pub const TUI_LATENCY_HISTORY_CAPACITY: usize = 60;
1435
1436/// Buffer utilization history capacity for TUI sparkline.
1437pub const TUI_BUFFER_UTIL_HISTORY_CAPACITY: usize = 100;
1438
1439/// Log buffer capacity for TUI log panel.
1440pub const TUI_LOG_BUFFER_CAPACITY: usize = 1000;
1441
1442/// TUI tick/refresh interval (milliseconds).
1443pub const TUI_TICK_INTERVAL_MS: u64 = 500;
1444
1445/// When a file's hole ratio (bytes in holes / total bytes) exceeds this threshold,
1446/// skip fallocate pre-allocation. The io_uring pipeline will punch holes as needed.
1447/// This avoids the wasteful allocate-then-punch round-trip for borderline-sparse files.
1448pub const SPARSE_HOLE_RATIO_SKIP_THRESHOLD: f64 = 0.5;
1449
1450// --- NFS NSS / Hostname / XDR Encoder Capacities ---
1451
1452/// NSS getpwuid_r / getgrgid_r username/group lookup buffer size.
1453pub const NFS_NSS_BUFFER_SIZE: usize = 1024;
1454
1455/// Hostname buffer for gethostname() syscall.
1456pub const NFS_HOSTNAME_BUFFER_SIZE: usize = 256;
1457
1458/// Initial XDR encoder capacity for compound RPC body.
1459pub const NFS_XDR_ENCODER_BODY_CAPACITY: usize = 4096;
1460
1461/// Initial XDR encoder capacity for small RPC messages (EXCHANGE_ID, CREATE_SESSION).
1462pub const NFS_XDR_ENCODER_SMALL_CAPACITY: usize = 512;
1463
1464/// Initial XDR encoder capacity for GSS RPC header.
1465pub const NFS_XDR_ENCODER_TINY_CAPACITY: usize = 256;
1466
1467/// Number of grace period retries for NFS WRITE operations.
1468pub const NFS_GRACE_RETRY_COUNT: usize = 3;
1469
1470// --- Similarity / Delta Encoding ---
1471
1472/// Minimum data length in bytes for TLSH computation.
1473pub const TLSH_MIN_DATA_SIZE: usize = 50;
1474
1475/// Entropy threshold above which TLSH is skipped (encrypted/compressed data).
1476pub const TLSH_ENTROPY_SKIP_THRESHOLD: f32 = 7.9;
1477
1478/// Maximum input size for delta encoding (64KB).
1479pub const DELTA_MAX_INPUT_SIZE: usize = 65_536;
1480
1481/// Minimum match length for a delta Copy operation.
1482pub const DELTA_MIN_MATCH_LEN: usize = 8;
1483
1484/// Match length considered "good enough" to stop early search in delta encoding.
1485pub const DELTA_GOOD_MATCH_LEN: usize = 256;
1486
1487// --- Chunker ---
1488
1489/// Maximum input size for the chunk_reader function (16MB).
1490pub const CHUNK_READER_MAX_INPUT: usize = 16 * 1024 * 1024;
1491
1492/// Read buffer size for chunk_reader.
1493pub const CHUNK_READER_READ_BUFFER_SIZE: usize = 8192;
1494
1495// --- BufferPool ---
1496
1497/// Maximum number of registered buffers in a BufferPool.
1498pub const BUFFER_POOL_MAX_REGISTERED_BUFFERS: u32 = 65535;
1499
1500// --- Timers / Poll Intervals ---
1501
1502/// Poll sleep interval for version index scan (milliseconds).
1503pub const VERSION_SCAN_POLL_INTERVAL_MS: u64 = 100;
1504
1505/// TUI browser event poll interval (milliseconds).
1506pub const BROWSER_EVENT_POLL_INTERVAL_MS: u64 = 100;
1507
1508/// Minimum Kerberos ticket remaining lifetime before renewal (seconds).
1509pub const KRB5_TICKET_MIN_REMAINING_SECS: u64 = 60;
1510
1511#[cfg(test)]
1512mod tests {
1513    #![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
1514    use super::*;
1515
1516    /// Verify effort-tier constants maintain strict ordering.
1517    /// Quick < Balanced < Deep for content, prompt, and preview char limits.
1518    #[test]
1519    fn test_constants_ordering_invariants() {
1520        // Content char limits must increase by effort level
1521        assert!(
1522            AI_QUICK_MAX_CONTENT_CHARS < AI_BALANCED_MAX_CONTENT_CHARS,
1523            "QUICK ({}) must be < BALANCED ({})",
1524            AI_QUICK_MAX_CONTENT_CHARS,
1525            AI_BALANCED_MAX_CONTENT_CHARS
1526        );
1527        assert!(
1528            AI_BALANCED_MAX_CONTENT_CHARS < AI_DEEP_MAX_CONTENT_CHARS,
1529            "BALANCED ({}) must be < DEEP ({})",
1530            AI_BALANCED_MAX_CONTENT_CHARS,
1531            AI_DEEP_MAX_CONTENT_CHARS
1532        );
1533
1534        // Prompt char limits must increase by effort level
1535        assert!(
1536            AI_QUICK_MAX_PROMPT_CHARS < AI_BALANCED_MAX_PROMPT_CHARS,
1537            "QUICK prompt ({}) must be < BALANCED ({})",
1538            AI_QUICK_MAX_PROMPT_CHARS,
1539            AI_BALANCED_MAX_PROMPT_CHARS
1540        );
1541        assert!(
1542            AI_BALANCED_MAX_PROMPT_CHARS < AI_DEEP_MAX_PROMPT_CHARS,
1543            "BALANCED prompt ({}) must be < DEEP ({})",
1544            AI_BALANCED_MAX_PROMPT_CHARS,
1545            AI_DEEP_MAX_PROMPT_CHARS
1546        );
1547
1548        // Preview char limits must increase by effort level
1549        assert!(
1550            AI_QUICK_MAX_PREVIEW_CHARS < AI_BALANCED_MAX_PREVIEW_CHARS,
1551            "QUICK preview ({}) must be < BALANCED ({})",
1552            AI_QUICK_MAX_PREVIEW_CHARS,
1553            AI_BALANCED_MAX_PREVIEW_CHARS
1554        );
1555        assert!(
1556            AI_BALANCED_MAX_PREVIEW_CHARS < AI_DEEP_MAX_PREVIEW_CHARS,
1557            "BALANCED preview ({}) must be < DEEP ({})",
1558            AI_BALANCED_MAX_PREVIEW_CHARS,
1559            AI_DEEP_MAX_PREVIEW_CHARS
1560        );
1561
1562        // Embed byte cap must be positive and reasonable
1563        assert!(AI_MAX_EMBED_BYTES > 0);
1564        assert!(AI_MAX_EMBED_BYTES <= 10 * 1024 * 1024); // <= 10 MiB sanity cap
1565    }
1566}