v7.29.0 β subtype primitive + trackField + migrateField
Affected products: anyone modeling entities with per-product sub-classification β every
consumer that's been reaching for metadata.kind, a custom metadata.subtype field, a
data.kind shape inside the payload, or similar ad-hoc conventions. Additive; drop-in from
7.28.x. No deprecations.
New β subtype promoted to a top-level standard field
subtype?: string is now a first-class standard field on every entity, alongside type /
confidence / weight. Use it as the platform-standard primitive for sub-classifying entities
within a NounType (Person β 'employee' / 'customer'; Document β 'invoice' / 'contract';
Event β 'milestone' / 'meeting'):
await brain.add({
data: 'Avery Brooks β runs the AI lab',
type: NounType.Person,
subtype: 'employee', // top-level write param
metadata: { department: 'ai-lab' }
})
// Fast-path filter β column-store hit, not metadata fallback:
const employees = await brain.find({ type: NounType.Person, subtype: 'employee' })
// Set membership:
const internal = await brain.find({
type: NounType.Person,
subtype: ['employee', 'contractor']
})Flat string, no hierarchy β your vocabulary, your choice. Brainy stores and counts, never validates.
New β O(1) subtype counts via the persisted rollup
A new _system/subtype-statistics.json rollup is maintained incrementally as entities are added,
updated, and deleted β mirroring the existing nounCountsByType machinery with the same self-heal
behavior on poison detection. Counts are O(1) at billion scale:
brain.counts.bySubtype(NounType.Person)
// β { employee: 12, customer: 847, vendor: 34 }
brain.counts.bySubtype(NounType.Person, 'employee') // O(1) point count
// β 12
brain.counts.topSubtypes(NounType.Person, 3)
// β [['customer', 847], ['employee', 12], ['vendor', 34]]
brain.subtypesOf(NounType.Person)
// β ['customer', 'employee', 'vendor']New β brain.trackField() for other metadata facets
For facets that aren't the primary sub-classification (status, source, role, paradigm),
trackField registers a field for cardinality + per-NounType breakdown stats without promoting
each one to a top-level slot. Piggybacks on the existing aggregation engine, so backfill-on-define
applies β registering on a populated brain scans existing entities on the first query:
brain.trackField('status', { perType: true })
await brain.counts.byField('status')
// β { todo: 12, doing: 3, done: 47 }
await brain.counts.byField('status', { type: NounType.Task })
// β { todo: 8, doing: 2, done: 30 }
// Opt-in vocabulary validation:
brain.trackField('priority', { values: ['low', 'medium', 'high'] })
// brain.add({ ..., metadata: { priority: 'urgent' } }) β throwsNew β generic brain.migrateField() for one-shot rewrites
Streams every entity and copies a value from one field path to another. Supports top-level
standard fields, metadata.*, and data.* paths; idempotent; with optional readBoth: true
deprecation window that preserves the source field alongside the new one:
// Phase 1: dual-populate (legacy readers still work)
await brain.migrateField({
from: 'metadata.kind',
to: 'subtype',
readBoth: true
})
// ...readers migrate to subtype at their own pace...
// Phase 2: clear the source field
await brain.migrateField({ from: 'metadata.kind', to: 'subtype' })
// β { scanned: 1500, migrated: 1500, skipped: 0, errors: [] }Supports batchSize and onProgress for large brains.
Aggregation composition
subtype is a standard-field group-by dimension out of the box β no where: wrapper, no
metadata-fallback overhead:
await brain.find({
aggregate: {
groupBy: ['type', 'subtype'],
metrics: { count: { op: 'COUNT' } }
}
})
// [
// { groupKey: { type: 'person', subtype: 'customer' }, count: 847 },
// { groupKey: { type: 'person', subtype: 'employee' }, count: 12 },
// { groupKey: { type: 'document', subtype: 'invoice' }, count: 2103 },
// ...
// ]Cortex compatibility
Subtype works under Cortex out of the box via auto-field-indexing. Cortex will land its own
native-side query-planner recognition + subtypeCountsByType native rollup in the next Cortex
release for full parity with type's fast path. Not a Brainy blocker β subtype reads/writes
function correctly with current Cortex.
Docs
Full guide: docs/guides/subtypes-and-facets.md. Subtype is documented as a core primitive
throughout README.md, docs/DATA_MODEL.md, docs/architecture/finite-type-system.md,
docs/api/README.md, and docs/QUERY_OPERATORS.md.