refactor(8.0): remove the 4 deprecated query-operator aliases (clean break)

8.0 keeps the canonical operators (eq/ne/gt/gte/lt/lte) and their clean
long-form aliases (equals/notEquals/greaterThan/greaterThanOrEqual/lessThan/
lessThanOrEqual), and drops the four redundant deprecated spellings:
  is → eq,  isNot → ne,  greaterEqual → gte,  lessEqual → lte

Removed from every evaluator (metadataIndex criteria + range switches,
metadataFilter, the db whereMatcher egress path) and from the
BrainyFieldOperators type, the unsupported-operator error message, the docs
(QUERY_OPERATORS / api README / VFS projection + semantic guides), and the
whereMatcher alias tests. Also migrated Brainy's own internal use — the VFS
TemporalProjection queried with greaterEqual/lessEqual, which would have
silently broken — to gte/lte.

Full gate green: build, unit 1512, integration 607.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
David Snelling 2026-06-29 10:29:20 -07:00
parent b9369f260b
commit ddcc0c723d
9 changed files with 45 additions and 68 deletions

View file

@ -10,8 +10,8 @@ All operators work with `find({ where: { ... } })` and filter on **metadata fiel
| Operator | Alias | Description | Example |
|----------|-------|-------------|---------|
| `equals` | `eq`, `is` | Exact match | `{ status: { equals: 'active' } }` |
| `notEquals` | `ne`, `isNot` | Not equal | `{ status: { notEquals: 'deleted' } }` |
| `eq` | `equals` | Exact match | `{ status: { eq: 'active' } }` |
| `ne` | `notEquals` | Not equal | `{ status: { ne: 'deleted' } }` |
**Shorthand:** A bare value is treated as `equals`:
@ -27,10 +27,10 @@ brain.find({ where: { status: { equals: 'active' } } })
| Operator | Alias | Description | Example |
|----------|-------|-------------|---------|
| `greaterThan` | `gt` | Greater than | `{ age: { greaterThan: 18 } }` |
| `greaterEqual` | `gte` | Greater or equal | `{ score: { greaterEqual: 90 } }` |
| `lessThan` | `lt` | Less than | `{ price: { lessThan: 100 } }` |
| `lessEqual` | `lte` | Less or equal | `{ rating: { lessEqual: 3 } }` |
| `gt` | `greaterThan` | Greater than | `{ age: { gt: 18 } }` |
| `gte` | `greaterThanOrEqual` | Greater or equal | `{ score: { gte: 90 } }` |
| `lt` | `lessThan` | Less than | `{ price: { lt: 100 } }` |
| `lte` | `lessThanOrEqual` | Less or equal | `{ rating: { lte: 3 } }` |
| `between` | — | Inclusive range `[min, max]` | `{ year: { between: [2020, 2025] } }` |
```typescript
@ -160,9 +160,9 @@ Brainy's MetadataIndex supports a subset of operators natively for O(1) field lo
| `equals` / `eq` | Yes | Yes |
| `notEquals` / `ne` | — | Yes |
| `greaterThan` / `gt` | Yes | Yes |
| `greaterEqual` / `gte` | Yes | Yes |
| `greaterThanOrEqual` / `gte` | Yes | Yes |
| `lessThan` / `lt` | Yes | Yes |
| `lessEqual` / `lte` | Yes | Yes |
| `lessThanOrEqual` / `lte` | Yes | Yes |
| `between` | Yes | Yes |
| `oneOf` / `in` | Yes | Yes |
| `noneOf` | — | Yes |

View file

@ -413,9 +413,9 @@ Brainy uses clean, readable operators (BFO — Brainy Field Operators):
| `equals` / `eq` | Exact match | `{age: {equals: 25}}` |
| `notEquals` / `ne` | Not equal | `{status: {notEquals: 'deleted'}}` |
| `greaterThan` / `gt` | Greater than | `{age: {greaterThan: 18}}` |
| `greaterEqual` / `gte` | Greater or equal | `{score: {greaterEqual: 90}}` |
| `gte` / `greaterThanOrEqual` | Greater or equal | `{score: {gte: 90}}` |
| `lessThan` / `lt` | Less than | `{price: {lessThan: 100}}` |
| `lessEqual` / `lte` | Less or equal | `{rating: {lessEqual: 3}}` |
| `lte` / `lessThanOrEqual` | Less or equal | `{rating: {lte: 3}}` |
| `between` | Inclusive range | `{year: {between: [2020, 2025]}}` |
| `oneOf` / `in` | In array | `{color: {oneOf: ['red', 'blue']}}` |
| `noneOf` | Not in array | `{status: {noneOf: ['deleted']}}` |

View file

@ -289,7 +289,7 @@ export class SizeProjection extends BaseProjectionStrategy {
where: {
vfsType: 'file',
size: {
greaterEqual: min,
gte: min,
lessThan: max
}
},
@ -305,7 +305,7 @@ export class SizeProjection extends BaseProjectionStrategy {
where: {
vfsType: 'file',
size: {
greaterEqual: min,
gte: min,
lessThan: max
}
},
@ -359,7 +359,7 @@ export class StatusProjection extends BaseProjectionStrategy {
const results = await brain.find({
where: {
vfsType: 'file',
modified: { greaterEqual: oneDayAgo },
modified: { gte: oneDayAgo },
reviewStatus: { missing: true } // No review status set
},
limit: 1000
@ -387,7 +387,7 @@ export class StatusProjection extends BaseProjectionStrategy {
vfsType: 'file',
anyOf: [
{ reviewStatus: { exists: true } },
{ modified: { greaterEqual: Date.now() - 86400000 } }
{ modified: { gte: Date.now() - 86400000 } }
]
},
limit
@ -415,7 +415,7 @@ Projection strategies use **Brainy Field Operators** (BFO), not MongoDB-style op
{ size: { $gte: 1000, $lte: 5000 } }
// ✅ BFO style (CORRECT)
{ size: { greaterEqual: 1000, lessEqual: 5000 } }
{ size: { gte: 1000, lte: 5000 } }
```
### Logical Operators
@ -451,9 +451,9 @@ Projection strategies use **Brainy Field Operators** (BFO), not MongoDB-style op
// Comparison
{ field: value } // Exact match
{ field: { greaterThan: 10 } } // >
{ field: { greaterEqual: 10 } } // >=
{ field: { gte: 10 } } // >=
{ field: { lessThan: 10 } } // <
{ field: { lessEqual: 10 } } // <=
{ field: { lte: 10 } } // <=
{ field: { not: value } } // !=
// Logical
@ -485,7 +485,7 @@ All metadata fields are automatically indexed. Use direct equality or range quer
```typescript
// ✅ Fast: Direct index lookup (O(log n))
{ priority: 'high' }
{ size: { greaterEqual: 1000 } }
{ size: { gte: 1000 } }
// ⚠️ Slower: Must scan results
{ path: { matches: /complex-regex/ } }
@ -668,7 +668,7 @@ async resolve(brain, vfs, period: string) {
const results = await brain.find({
where: {
modified: { greaterEqual: since }
modified: { gte: since }
}
})
return this.extractIds(results)

View file

@ -127,7 +127,7 @@ await vfs.readFile('/as-of/2024-03-15/auth.ts')
// the path only resolves if auth.ts was modified that day
```
**How it works:** Tracks the `modified` timestamp on every file and runs a range query (`greaterEqual`/`lessEqual`) over one 24-hour window for O(log n) performance. The VFS does not store historical file contents — `/as-of/` filters by *when a file last changed*; reads return the current bytes. For point-in-time state, use the Db API (`brain.asOf(generation)`).
**How it works:** Tracks the `modified` timestamp on every file and runs a range query (`gte`/`lte`) over one 24-hour window for O(log n) performance. The VFS does not store historical file contents — `/as-of/` filters by *when a file last changed*; reads return the current bytes. For point-in-time state, use the Db API (`brain.asOf(generation)`).
**Status:** ✅ Fully implemented and tested at 10K file scale