2025-10-22 17:36:27 -07:00
import { describe , it , expect } from 'vitest'
import {
autoDetectPreset ,
getPreset ,
getPresetNames ,
explainPresetChoice ,
createCustomPreset ,
validatePreset ,
formatPreset ,
FAST_PRESET ,
BALANCED_PRESET ,
ACCURATE_PRESET ,
EXPLICIT_PRESET ,
PATTERN_PRESET ,
PRESETS ,
type ImportContext ,
type PresetConfig
} from '../../../src/neural/presets.js'
describe ( 'Presets' , ( ) = > {
describe ( 'preset definitions' , ( ) = > {
it ( 'should have all 5 presets defined' , ( ) = > {
expect ( PRESETS ) . toBeDefined ( )
expect ( Object . keys ( PRESETS ) ) . toHaveLength ( 5 )
expect ( PRESETS . fast ) . toBe ( FAST_PRESET )
expect ( PRESETS . balanced ) . toBe ( BALANCED_PRESET )
expect ( PRESETS . accurate ) . toBe ( ACCURATE_PRESET )
expect ( PRESETS . explicit ) . toBe ( EXPLICIT_PRESET )
expect ( PRESETS . pattern ) . toBe ( PATTERN_PRESET )
} )
it ( 'should have valid fast preset' , ( ) = > {
expect ( FAST_PRESET . name ) . toBe ( 'fast' )
expect ( FAST_PRESET . signals . enabled ) . toEqual ( [ 'exact' , 'pattern' ] )
expect ( FAST_PRESET . strategies . enabled ) . toEqual ( [ 'explicit' ] )
expect ( FAST_PRESET . streaming ) . toBe ( true )
expect ( FAST_PRESET . strategies . earlyTermination ) . toBe ( true )
} )
it ( 'should have valid balanced preset' , ( ) = > {
expect ( BALANCED_PRESET . name ) . toBe ( 'balanced' )
expect ( BALANCED_PRESET . signals . enabled ) . toEqual ( [ 'exact' , 'embedding' , 'pattern' ] )
expect ( BALANCED_PRESET . strategies . enabled ) . toEqual ( [ 'explicit' , 'pattern' , 'embedding' ] )
expect ( BALANCED_PRESET . streaming ) . toBe ( false )
} )
it ( 'should have valid accurate preset' , ( ) = > {
expect ( ACCURATE_PRESET . name ) . toBe ( 'accurate' )
expect ( ACCURATE_PRESET . signals . enabled ) . toEqual ( [ 'exact' , 'embedding' , 'pattern' , 'context' ] )
expect ( ACCURATE_PRESET . strategies . enabled ) . toEqual ( [ 'explicit' , 'pattern' , 'embedding' ] )
expect ( ACCURATE_PRESET . strategies . earlyTermination ) . toBe ( false )
} )
it ( 'should have valid explicit preset' , ( ) = > {
expect ( EXPLICIT_PRESET . name ) . toBe ( 'explicit' )
expect ( EXPLICIT_PRESET . signals . enabled ) . toEqual ( [ 'exact' , 'pattern' ] )
expect ( EXPLICIT_PRESET . strategies . enabled ) . toEqual ( [ 'explicit' , 'pattern' ] )
expect ( EXPLICIT_PRESET . strategies . minConfidence ) . toBeGreaterThanOrEqual ( 0.80 )
} )
it ( 'should have valid pattern preset' , ( ) = > {
expect ( PATTERN_PRESET . name ) . toBe ( 'pattern' )
expect ( PATTERN_PRESET . signals . enabled ) . toEqual ( [ 'embedding' , 'pattern' , 'context' ] )
expect ( PATTERN_PRESET . strategies . enabled ) . toEqual ( [ 'pattern' , 'embedding' ] )
} )
} )
describe ( 'autoDetectPreset' , ( ) = > {
it ( 'should return fast preset for large datasets' , ( ) = > {
const context : ImportContext = {
rowCount : 15000 ,
fileSize : 5_000_000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'fast' )
} )
it ( 'should return fast preset for large files' , ( ) = > {
const context : ImportContext = {
fileSize : 15_000_000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'fast' )
} )
it ( 'should return accurate preset for small datasets' , ( ) = > {
const context : ImportContext = {
rowCount : 50
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'accurate' )
} )
it ( 'should return explicit preset for Excel with explicit columns' , ( ) = > {
const context : ImportContext = {
fileType : 'excel' ,
hasExplicitColumns : true ,
rowCount : 500
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'explicit' )
} )
it ( 'should return explicit preset for CSV with explicit columns' , ( ) = > {
const context : ImportContext = {
fileType : 'csv' ,
hasExplicitColumns : true
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'explicit' )
} )
it ( 'should return pattern preset for PDF files' , ( ) = > {
const context : ImportContext = {
fileType : 'pdf' ,
rowCount : 200
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'pattern' )
} )
it ( 'should return pattern preset for Markdown files' , ( ) = > {
const context : ImportContext = {
fileType : 'markdown'
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'pattern' )
} )
it ( 'should return pattern preset for narrative content' , ( ) = > {
const context : ImportContext = {
hasNarrativeContent : true ,
rowCount : 300
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'pattern' )
} )
it ( 'should return pattern preset for long definitions' , ( ) = > {
const context : ImportContext = {
avgDefinitionLength : 800 ,
fileType : 'csv'
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'pattern' )
} )
it ( 'should return balanced preset for JSON' , ( ) = > {
const context : ImportContext = {
fileType : 'json' ,
rowCount : 500
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' )
} )
it ( 'should return balanced preset for medium datasets' , ( ) = > {
const context : ImportContext = {
fileType : 'excel' ,
rowCount : 2000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' )
} )
it ( 'should return balanced preset for empty context' , ( ) = > {
const preset = autoDetectPreset ( )
expect ( preset . name ) . toBe ( 'balanced' )
} )
it ( 'should return balanced preset for unknown file type' , ( ) = > {
const context : ImportContext = {
fileType : 'unknown' ,
rowCount : 500
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' )
} )
} )
describe ( 'getPreset' , ( ) = > {
it ( 'should get preset by name' , ( ) = > {
expect ( getPreset ( 'fast' ) ) . toBe ( FAST_PRESET )
expect ( getPreset ( 'balanced' ) ) . toBe ( BALANCED_PRESET )
expect ( getPreset ( 'accurate' ) ) . toBe ( ACCURATE_PRESET )
expect ( getPreset ( 'explicit' ) ) . toBe ( EXPLICIT_PRESET )
expect ( getPreset ( 'pattern' ) ) . toBe ( PATTERN_PRESET )
} )
it ( 'should be case-insensitive' , ( ) = > {
expect ( getPreset ( 'FAST' ) ) . toBe ( FAST_PRESET )
expect ( getPreset ( 'Balanced' ) ) . toBe ( BALANCED_PRESET )
expect ( getPreset ( 'EXPLICIT' ) ) . toBe ( EXPLICIT_PRESET )
} )
it ( 'should throw error for unknown preset' , ( ) = > {
expect ( ( ) = > getPreset ( 'unknown' ) ) . toThrow ( 'Unknown preset: unknown' )
} )
} )
describe ( 'getPresetNames' , ( ) = > {
it ( 'should return all preset names' , ( ) = > {
const names = getPresetNames ( )
expect ( names ) . toHaveLength ( 5 )
expect ( names ) . toContain ( 'fast' )
expect ( names ) . toContain ( 'balanced' )
expect ( names ) . toContain ( 'accurate' )
expect ( names ) . toContain ( 'explicit' )
expect ( names ) . toContain ( 'pattern' )
} )
} )
describe ( 'explainPresetChoice' , ( ) = > {
it ( 'should explain large dataset choice' , ( ) = > {
const context : ImportContext = {
rowCount : 15000 ,
fileSize : 12_000_000
}
const explanation = explainPresetChoice ( context )
expect ( explanation ) . toContain ( 'Large dataset' )
expect ( explanation ) . toContain ( '15000 rows' )
expect ( explanation ) . toContain ( 'fast preset' )
} )
it ( 'should explain small dataset choice' , ( ) = > {
const context : ImportContext = {
rowCount : 50
}
const explanation = explainPresetChoice ( context )
expect ( explanation ) . toContain ( 'Small critical dataset' )
expect ( explanation ) . toContain ( '50 rows' )
expect ( explanation ) . toContain ( 'accurate preset' )
} )
it ( 'should explain explicit columns choice' , ( ) = > {
const context : ImportContext = {
fileType : 'excel' ,
hasExplicitColumns : true
}
const explanation = explainPresetChoice ( context )
expect ( explanation ) . toContain ( 'EXCEL' )
expect ( explanation ) . toContain ( 'explicit relationship columns' )
expect ( explanation ) . toContain ( 'explicit preset' )
} )
it ( 'should explain narrative content choice' , ( ) = > {
const context : ImportContext = {
fileType : 'pdf' ,
hasNarrativeContent : true
}
const explanation = explainPresetChoice ( context )
expect ( explanation ) . toContain ( 'Narrative content' )
expect ( explanation ) . toContain ( 'pattern preset' )
} )
it ( 'should explain default choice' , ( ) = > {
const context : ImportContext = {
rowCount : 500
}
const explanation = explainPresetChoice ( context )
expect ( explanation ) . toContain ( 'balanced preset' )
} )
} )
describe ( 'createCustomPreset' , ( ) = > {
it ( 'should create custom preset from base' , ( ) = > {
const custom = createCustomPreset ( 'balanced' , {
name : 'my-custom' ,
batchSize : 2000
} )
expect ( custom . name ) . toBe ( 'my-custom' )
expect ( custom . batchSize ) . toBe ( 2000 )
expect ( custom . signals ) . toEqual ( BALANCED_PRESET . signals )
expect ( custom . strategies ) . toEqual ( BALANCED_PRESET . strategies )
} )
it ( 'should override signals' , ( ) = > {
const custom = createCustomPreset ( 'fast' , {
signals : {
enabled : [ 'embedding' ] ,
weights : { embedding : 1.0 , exact : 0 , pattern : 0 , context : 0 } ,
timeout : 200
}
} )
expect ( custom . signals . enabled ) . toEqual ( [ 'embedding' ] )
expect ( custom . signals . timeout ) . toBe ( 200 )
} )
it ( 'should override strategies' , ( ) = > {
const custom = createCustomPreset ( 'balanced' , {
strategies : {
enabled : [ 'pattern' ] ,
timeout : 500 ,
earlyTermination : false ,
minConfidence : 0.75
}
} )
expect ( custom . strategies . enabled ) . toEqual ( [ 'pattern' ] )
expect ( custom . strategies . timeout ) . toBe ( 500 )
expect ( custom . strategies . earlyTermination ) . toBe ( false )
} )
it ( 'should merge partial signal overrides' , ( ) = > {
const custom = createCustomPreset ( 'balanced' , {
signals : {
timeout : 300
} as any
} )
expect ( custom . signals . enabled ) . toEqual ( BALANCED_PRESET . signals . enabled )
expect ( custom . signals . timeout ) . toBe ( 300 )
} )
} )
describe ( 'validatePreset' , ( ) = > {
it ( 'should validate all built-in presets' , ( ) = > {
expect ( ( ) = > validatePreset ( FAST_PRESET ) ) . not . toThrow ( )
expect ( ( ) = > validatePreset ( BALANCED_PRESET ) ) . not . toThrow ( )
expect ( ( ) = > validatePreset ( ACCURATE_PRESET ) ) . not . toThrow ( )
expect ( ( ) = > validatePreset ( EXPLICIT_PRESET ) ) . not . toThrow ( )
expect ( ( ) = > validatePreset ( PATTERN_PRESET ) ) . not . toThrow ( )
} )
it ( 'should reject preset with no signals' , ( ) = > {
const invalid : PresetConfig = {
. . . BALANCED_PRESET ,
signals : {
. . . BALANCED_PRESET . signals ,
enabled : [ ]
}
}
expect ( ( ) = > validatePreset ( invalid ) ) . toThrow ( 'at least one enabled signal' )
} )
it ( 'should reject preset with no strategies' , ( ) = > {
const invalid : PresetConfig = {
. . . BALANCED_PRESET ,
strategies : {
. . . BALANCED_PRESET . strategies ,
enabled : [ ]
}
}
expect ( ( ) = > validatePreset ( invalid ) ) . toThrow ( 'at least one enabled strategy' )
} )
it ( 'should reject preset with invalid weight sum' , ( ) = > {
const invalid : PresetConfig = {
. . . BALANCED_PRESET ,
signals : {
enabled : [ 'exact' , 'embedding' ] ,
weights : {
exact : 0.3 ,
embedding : 0.5 ,
pattern : 0 ,
context : 0
} ,
timeout : 100
}
}
expect ( ( ) = > validatePreset ( invalid ) ) . toThrow ( 'weights must sum to 1.0' )
} )
it ( 'should reject preset with negative timeout' , ( ) = > {
const invalid : PresetConfig = {
. . . BALANCED_PRESET ,
signals : {
. . . BALANCED_PRESET . signals ,
timeout : - 100
}
}
expect ( ( ) = > validatePreset ( invalid ) ) . toThrow ( 'Timeouts must be positive' )
} )
it ( 'should reject preset with invalid batch size' , ( ) = > {
const invalid : PresetConfig = {
. . . BALANCED_PRESET ,
batchSize : 0
}
expect ( ( ) = > validatePreset ( invalid ) ) . toThrow ( 'Batch size must be positive' )
} )
} )
describe ( 'formatPreset' , ( ) = > {
it ( 'should format preset for display' , ( ) = > {
const formatted = formatPreset ( BALANCED_PRESET )
expect ( formatted ) . toContain ( 'Preset: balanced' )
expect ( formatted ) . toContain ( 'Description:' )
expect ( formatted ) . toContain ( 'Signals:' )
expect ( formatted ) . toContain ( 'exact: 40%' )
expect ( formatted ) . toContain ( 'embedding: 35%' )
expect ( formatted ) . toContain ( 'Strategies:' )
expect ( formatted ) . toContain ( 'explicit' )
expect ( formatted ) . toContain ( 'pattern' )
expect ( formatted ) . toContain ( 'embedding' )
expect ( formatted ) . toContain ( 'Streaming: false' )
expect ( formatted ) . toContain ( 'Batch size: 500' )
} )
it ( 'should format fast preset correctly' , ( ) = > {
const formatted = formatPreset ( FAST_PRESET )
expect ( formatted ) . toContain ( 'fast' )
expect ( formatted ) . toContain ( 'Streaming: true' )
expect ( formatted ) . toContain ( 'Early termination: true' )
} )
} )
describe ( 'preset priorities' , ( ) = > {
it ( 'should prioritize size over explicit columns for large datasets' , ( ) = > {
const context : ImportContext = {
rowCount : 20000 ,
fileType : 'excel' ,
hasExplicitColumns : true
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'fast' ) // Size trumps explicit
} )
it ( 'should prioritize small size over other factors' , ( ) = > {
const context : ImportContext = {
rowCount : 50 ,
fileType : 'pdf' ,
hasNarrativeContent : true
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'accurate' ) // Small size trumps pattern
} )
it ( 'should prioritize explicit columns over narrative for Excel' , ( ) = > {
const context : ImportContext = {
rowCount : 500 ,
fileType : 'excel' ,
hasExplicitColumns : true ,
hasNarrativeContent : true
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'explicit' ) // Explicit trumps narrative
} )
} )
describe ( 'edge cases' , ( ) = > {
it ( 'should handle zero row count' , ( ) = > {
const context : ImportContext = {
rowCount : 0 ,
fileType : 'csv'
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' )
} )
it ( 'should handle boundary row count (exactly 100)' , ( ) = > {
const context : ImportContext = {
rowCount : 100
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' ) // Not accurate (< 100)
} )
it ( 'should handle boundary row count (exactly 10000)' , ( ) = > {
const context : ImportContext = {
rowCount : 10000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' ) // Not fast (> 10000)
} )
it ( 'should handle missing hasExplicitColumns flag' , ( ) = > {
const context : ImportContext = {
fileType : 'excel' ,
rowCount : 500
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' )
} )
} )
describe ( 'real-world scenarios' , ( ) = > {
fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location
Brainy 7.30.0 introduced a memory-derived synchronous cap on `find({ limit })`
to prevent OOM. The cap was sound in intent but ~4x too conservative in
calibration: assumed 100 KB per result while typical entity footprint is 7-10 KB
(384-dim float32 vector ≈ 1.5 KB + standard fields + metadata). On a 900 MB
free-memory box the cap derived to 9000 — breaking common safety-cap patterns
like `find({ type, where, limit: 10_000 })` that typically return 10-500
entities. Surfaced as a runtime regression with cascading 500s degrading
production dashboards.
Three concurrent fixes:
A. RECALIBRATE THE FORMULA
- src/utils/paramValidation.ts:175,196,212 — the three memory-derived priorities
(reservedQueryMemory / containerMemory / freeMemory) all divided by
100 * 1024 * 1024 (100 KB per result, ~10-15x over conservative). Replaced
with a new MAX_LIMIT_KB_PER_RESULT = 25 constant that matches observed
entity size.
- Result: 4 GB container cap goes 10_000 → 40_000; 2 GB cap goes 5_000 →
20_000; 900 MB free-memory cap goes 9_000 → ~36_000. 100k hard ceiling
unchanged. `maxQueryLimit` / `reservedQueryMemory` constructor overrides
unchanged in behavior.
B. TWO-TIER ENFORCEMENT (warn-then-throw)
- Below cap (limit <= maxLimit): silent pass, unchanged.
- Soft tier (maxLimit < limit <= 2 * maxLimit): NEW — one-time warning per
call site (dedup keyed on caller stack frame + limit value), query
proceeds. Pre-7.30.2 code that relied on the cap silently allowing typical
safety-cap limits keeps working; the warning teaches the recipe so consumers
can fix it intentionally.
- Hard tier (limit > 2 * maxLimit): throw with the same teaching message
format. Real OOM territory; the cap stops being a recommendation and becomes
a guardrail.
- The 2x soft margin absorbs typical safety-cap patterns (limit: 10_000
against a 9 K-cap box) without disabling OOM protection. Real OOM territory
on a JS in-memory brain is hundreds of thousands of results, not 10x the
safety cap.
C. IMPROVED ERROR / WARNING MESSAGE
- Same shape as the 7.30.1 enforcement-error messages: state the problem,
name the three escape valves (maxQueryLimit / reservedQueryMemory /
pagination), include caller location, link to docs.
- Extracted findCallerLocation() helper from brainy.ts to a new
src/utils/callerLocation.ts so both the subtype enforcement (7.30.1) and
the limit enforcement (7.30.2) share one implementation without circular
imports.
DOCS
- New docs/guides/find-limits.md (public: true) — full reference: why the cap
exists, the four memory sources the auto-config considers, the three escape
valves with when-to-use-which guidance, and an explicit "pagination is the
future-proof pattern" callout (8.0 may tighten the cap further; pagination
keeps working unchanged).
- docs/api/README.md find() entry gets a one-paragraph `limit` tip + pointer
to the new guide.
- RELEASES.md v7.30.2 entry.
TESTS
- New tests/integration/find-limits.test.ts (9 tests): below-cap silent pass;
soft-tier warns once per call site (dedup verified by exercising same vs.
different source lines via wrapper closures); soft-tier message format
(names all three escape valves + docs link); soft-tier message includes
caller location; hard-tier throws; hard-tier message format same as
soft-tier; consumer maxQueryLimit override raises the cap and shifts both
tiers accordingly; pre-7.30.2 regression scenario explicitly covered.
- tests/unit/utils/memoryLimits.test.ts — 4 tests updated for the recalibrated
cap values (hardcoded expected numbers bumped 4x to match new 25 KB/result
assumption).
- tests/unit/utils/paramValidation.test.ts — auto-limit test extended to cover
the three-tier semantics (below-cap pass / soft-tier silent / hard-tier
throw).
- Existing suites unchanged: subtype-and-facets 26/26, verb-subtype-and-
enforcement 30/30, strict-mode-self-test 13/13. Unit 1468/1468.
CORTEX COMPATIBILITY
- Zero Cortex changes required. Every change is JS-side: formula recalibration
runs in ValidationConfig.constructor(), two-tier enforcement runs in
validateFindParams(), both fire before any storage / index / Cortex call.
- The new guide notes that Brainy 8.0's Datomic-style Db.find() may tighten
per-call limits to keep snapshot semantics cheap; pagination remains the
pattern that's guaranteed to keep working.
REPO-WIDE CLEANUP
Brainy is the only Soulcraft project that is open source. This commit also
scrubs closed-source product names and product-specific class/field references
from every tracked file in the repo (src/, docs/, tests/, RELEASES.md,
CHANGELOG.md). Consumer-reported bugs, regression scenarios, and release
notes now refer to "a consumer", "a downstream application", "a production
deployment", or "an internal report" — never to the named product. Two
product-named test files renamed to neutral diagnostic names. CLAUDE.md gains
a project-level guard rule documenting the policy and an example list of the
identifiers that may not appear in tracked code.
Verification
- npx tsc --noEmit: clean
- npm test: 1468 / 1468 unit
- All four integration subtype + verb + strict + find-limits suites: 78/78
- npm run build: clean
- Closed-source product reference audit: clean
2026-06-08 12:34:05 -07:00
it ( 'should handle glossary correctly' , ( ) = > {
2025-10-22 17:36:27 -07:00
const context : ImportContext = {
fileType : 'excel' ,
rowCount : 567 ,
hasExplicitColumns : true , // Has "Related Terms" column
fileSize : 50_000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'explicit' )
const explanation = explainPresetChoice ( context )
expect ( explanation ) . toContain ( 'explicit' )
} )
it ( 'should handle large CSV import' , ( ) = > {
const context : ImportContext = {
fileType : 'csv' ,
rowCount : 50000 ,
fileSize : 25_000_000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'fast' )
expect ( preset . streaming ) . toBe ( true )
} )
it ( 'should handle PDF documentation' , ( ) = > {
const context : ImportContext = {
fileType : 'pdf' ,
rowCount : 150 ,
hasNarrativeContent : true ,
avgDefinitionLength : 600
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'pattern' )
} )
it ( 'should handle JSON API import' , ( ) = > {
const context : ImportContext = {
fileType : 'json' ,
rowCount : 1000 ,
fileSize : 500_000
}
const preset = autoDetectPreset ( context )
expect ( preset . name ) . toBe ( 'balanced' )
} )
} )
} )