feat: harden plugin system wiring and add developer diagnostics

Fix critical wiring bugs that prevented plugin-provided implementations
from being used at runtime. All CRUD operations, fork/checkout/clear,
batch embedding, neural APIs, and VFS path resolution now properly
dispatch through the plugin registry.

Changes:
- Wire graphIndex to storage for getVerbsBySource() fast path
- Replace instanceof checks with duck-typing (indexIsTypeAware flag)
  so plugin HNSW indexes work in add/update/delete/search
- Add createIndex() shared helper for plugin HNSW factory
- Fix fork/checkout/clear to use plugin factories for metadataIndex,
  graphIndex, and HNSW instead of hardcoding JS constructors
- Add three-tier embedBatch priority: embedBatch > embeddings > WASM
- Skip WASM warmup/eagerEmbeddings when plugin provides embeddings
- Fix PathResolver metadataIndex access (was looking on storage)
- Use global UnifiedCache in SemanticPathResolver
- Wire plugin distance function through neural APIs
- Add diagnostics() method and CLI command for provider inspection
- Add requireProviders() for production fail-fast assertions
- Add init-time provider summary log
- Add plugin developer documentation (docs/PLUGINS.md)
- Export DiagnosticsResult type
This commit is contained in:
David Snelling 2026-02-01 13:03:15 -08:00
parent 3a21bf62b7
commit 401e300ff2
12 changed files with 705 additions and 77 deletions

View file

@ -132,12 +132,14 @@ export interface LODConfig {
*/
export class NeuralAPI {
private brain: any // Brainy instance
private distanceFn: (a: Vector, b: Vector) => number
private similarityCache: Map<string, number> = new Map()
private clusterCache: Map<string, any> = new Map() // Enhanced for enterprise
private hierarchyCache: Map<string, SemanticHierarchy> = new Map()
constructor(brain: any) {
this.brain = brain
this.distanceFn = brain.distance || cosineDistance
}
// ===== SMART USER-FRIENDLY API =====
@ -471,7 +473,7 @@ export class NeuralAPI {
}
// Calculate similarity
const score = cosineDistance(itemA.vector, itemB.vector)
const score = this.distanceFn(itemA.vector, itemB.vector)
this.similarityCache.set(cacheKey, score)
@ -498,7 +500,7 @@ export class NeuralAPI {
}
private async similarityByVector(vectorA: Vector, vectorB: Vector, options?: SimilarityOptions): Promise<number | SimilarityResult> {
const score = cosineDistance(vectorA, vectorB)
const score = this.distanceFn(vectorA, vectorB)
if (options?.explain) {
return {
@ -610,7 +612,7 @@ export class NeuralAPI {
// Find minimum distance to existing sample
let minDistance = Infinity
for (const selected of sample) {
const distance = cosineDistance(candidate.vector, selected.vector)
const distance = this.distanceFn(candidate.vector, selected.vector)
minDistance = Math.min(minDistance, distance)
}
@ -652,7 +654,7 @@ export class NeuralAPI {
let bestDistance = Infinity
for (let c = 0; c < k; c++) {
const distance = cosineDistance(item.vector, centroids[c])
const distance = this.distanceFn(item.vector, centroids[c])
if (distance < bestDistance) {
bestDistance = distance
bestCluster = c
@ -679,7 +681,7 @@ export class NeuralAPI {
let bestDistance = Infinity
for (let cc = 0; cc < k; cc++) {
const distance = cosineDistance(item.vector, centroids[cc])
const distance = this.distanceFn(item.vector, centroids[cc])
if (distance < bestDistance) {
bestDistance = distance
bestCluster = cc
@ -750,7 +752,7 @@ export class NeuralAPI {
let merged = false
for (let i = 0; i < result.length; i++) {
const similarity = cosineDistance(result[i].centroid, batchCluster.centroid)
const similarity = this.distanceFn(result[i].centroid, batchCluster.centroid)
if (similarity > 0.8) {
// Merge clusters