-
released this
2026-06-05 20:16:15 +02:00 | 311 commits to main since this releaseAffected products: consumers modeling typed relationships with sub-classification
(direct vs dotted-line management; spouse / sibling / colleague; collaborator vs competitor;
etc.), and anyone wanting to enforce the pairing oftype+subtypeon every write.
Additive; drop-in from 7.29.x. No deprecations.Symmetric —
subtypeon relationships (parity with 7.29.0 nouns)subtype?: stringis now a first-class standard field on every relationship, mirroring the
noun-side work shipped in 7.29.0. Verbs and nouns are now first-class peers — every API
available on the noun side has a verb-side mirror.const ceoId = await brain.add({ type: NounType.Person, subtype: 'employee', data: 'Avery' }) const vpId = await brain.add({ type: NounType.Person, subtype: 'employee', data: 'Jordan' }) await brain.relate({ from: ceoId, to: vpId, type: VerbType.ReportsTo, subtype: 'direct' // sub-classification on the edge })Read & filter:
// Fast-path filter — column-store hit, not metadata fallback const direct = await brain.getRelations({ from: ceoId, type: VerbType.ReportsTo, subtype: 'direct' }) // Set membership const all = await brain.getRelations({ from: ceoId, type: VerbType.ReportsTo, subtype: ['direct', 'dotted-line'] }) // Traversal filter (depth-1 in JS; multi-hop lands on Cortex native) const reports = await brain.find({ connected: { from: ceoId, via: VerbType.ReportsTo, subtype: 'direct', depth: 1 } })New —
updateRelation()closes a long-standing gapVerbs previously had no update method — the only way to change a relationship was
delete-then-recreate, which lost the relation id. 7.30 shipsbrain.updateRelation():await brain.updateRelation({ id: relId, subtype: 'dotted-line' }) await brain.updateRelation({ id: relId, weight: 0.5, confidence: 0.9 }) // Change verb type — re-indexes in graph adjacency, id preserved await brain.updateRelation({ id: relId, type: VerbType.WorksWith })New — O(1) verb subtype counts via the persisted rollup
_system/verb-subtype-statistics.jsonmirrors the noun-side rollup shipped in 7.29.0.
Per-VerbType-per-subtype counts are maintained incrementally and persisted; reads are O(1):brain.counts.byRelationshipSubtype(VerbType.ReportsTo) // → { direct: 12, 'dotted-line': 3 } brain.counts.byRelationshipSubtype(VerbType.ReportsTo, 'direct') // O(1) point // → 12 brain.counts.topRelationshipSubtypes(VerbType.ReportsTo, 3) // → [['direct', 12], ['dotted-line', 3]] brain.relationshipSubtypesOf(VerbType.ReportsTo) // → ['direct', 'dotted-line']New —
brain.requireSubtype(type, options)per-type enforcementUnified API for noun OR verb types — register specific types as requiring a subtype,
optionally with a fixed vocabulary:brain.requireSubtype(NounType.Person, { values: ['employee', 'customer', 'vendor'], required: true }) brain.requireSubtype(VerbType.ReportsTo, { values: ['direct', 'dotted-line'], required: true }) // Now this throws — Person requires subtype: await brain.add({ type: NounType.Person, data: 'no subtype' }) // And this throws — 'matrix' isn't in the registered vocabulary: await brain.relate({ from: a, to: b, type: VerbType.ReportsTo, subtype: 'matrix' })New — Brain-wide strict mode
new Brainy({ requireSubtype: true })enforces subtype on every public write across the
whole brain. Composes with per-type rules; per-type rules win when both apply.// Every write must include subtype const brain = new Brainy({ requireSubtype: true }) // Exempt specific types (e.g. catch-all Thing) const brain2 = new Brainy({ requireSubtype: { except: [NounType.Thing, NounType.Custom] } })When strict mode is on:
- Every
add()/addMany()/update()/relate()/relateMany()/updateRelation()
rejects writes missing a subtype on a non-exempt type. addMany()andrelateMany()validate every item BEFORE any storage write —
atomic-fail semantics, no partial writes.- Brainy's own infrastructure writes (VFS root, directories, files) bypass via the
metadata.isVFSEntity: truemarker so existing consumers' VFS usage continues to work.
The brain-wide flag becomes the default in 8.0.0; the type-level
subtypefield becomes
required at the type system level. The full 8.0 contract upgrade is coordinated through the
internal platform handoff (CTX-SUBTYPE-8.0-CONTRACT).migrateField()extended to verbsThe migration helper shipped in 7.29.0 now walks verbs too via the new
entityKindoption:// Migrate verb-side metadata.kind → top-level subtype await brain.migrateField({ from: 'metadata.kind', to: 'subtype', entityKind: 'verb' }) // Or walk nouns and verbs in one pass await brain.migrateField({ from: 'metadata.kind', to: 'subtype', entityKind: 'both' })Default is
entityKind: 'noun'(backward-compatible).Symmetry — noun + verb capability matrix
7.30 closes every gap between nouns and verbs. Every capability available on the noun side
has a verb-side mirror:Capability Nouns Verbs subtypetop-level field✓ (7.29) ✓ (7.30 new) Standard-field set STANDARD_ENTITY_FIELDSSTANDARD_VERB_FIELDS(new)Field resolver helper resolveEntityFieldresolveVerbField(new)Statistics rollup _system/subtype-statistics.json_system/verb-subtype-statistics.json(new)Counts breakdown counts.bySubtype/topSubtypes/subtypesOfcounts.byRelationshipSubtype/topRelationshipSubtypes/relationshipSubtypesOf(new)Fast-path filter find({type, subtype})getRelations({type, subtype})+find({connected, subtype})(new)Update method update()updateRelation()(new — closed pre-7.30 gap)Migration helper migrateField()migrateField({entityKind: 'verb'|'both'})(new)Enforcement requireSubtype(NounType, ...)requireSubtype(VerbType, ...)— one unified APIBrain-wide strict mode new Brainy({ requireSubtype })covers bothsame Cortex compatibility
Verb subtype works under Cortex out of the box via auto-field-indexing. Cortex parity items
for the verb side (native query planner recognition,verbSubtypeCountsByTypenative rollup,
per-edge subtype on native graph adjacency for multi-hop traversal filtering) ship in the
next Cortex release. Not a Brainy blocker.Docs
Full guide:
docs/guides/subtypes-and-facets.md(extended with Layer V + Enforcement
sections). The verb subtype + enforcement APIs are documented indocs/api/README.md.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Every