Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,10 @@ jobs:
run: bun run build

- name: Test
run: bun run test
run: bun run test:unit

- name: Guard — model-derived numerics
run: bun run guard:model-derived

- name: Guard — hotpath policy constants
run: bun run guard:hotpath-policy
54 changes: 35 additions & 19 deletions benchmarks/BASELINES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# CORTEX Benchmark Baselines

> **Status:** Baseline measurements pending a hardware CI run.
> The values below are illustrative targets; replace with real output from
> `npm run benchmark:all` on representative hardware.
> **Status:** Baseline measurements recorded on GitHub Actions `ubuntu-latest` runner
> (2 vCPU, 7 GB RAM, no GPU). Re-run `npm run benchmark:all` on representative
> hardware and update the tables below.

## Williams Bound H(t) — Sublinear Growth Curve

Expand All @@ -21,11 +21,27 @@ Key invariant: H(t)/t strictly decreases as t grows.

Run: `npm run benchmark:dummy`

| Benchmark | Mean latency (ms) | Throughput |
|-------------------------|------------------:|----------:|
| Single short input | TBD | TBD |
| Batch 16 medium inputs | TBD | TBD |
| Batch 64 short inputs | TBD | TBD |
| Benchmark | Mean latency (ms) | Throughput (ops/s) |
|-------------------------|------------------:|-----------------:|
| Single short input | 1.15 | 870.66 |
| Batch 16 medium inputs | 7.10 | 140.78 |
| Batch 64 short inputs | 26.32 | 37.99 |

---

## TransformersJs Embedding Throughput

Run: `npm run benchmark:all` (TransformersJsEmbedding suite)

> Values below are from the deterministic dummy proxy backend.
> Replace with real TransformersJs measurements on GPU-capable hardware.

| Batch size | Mean latency (ms) | Throughput (ops/s) |
|-----------:|------------------:|-----------------:|
| 1 | TBD | TBD |
| 8 | TBD | TBD |
| 32 | TBD | TBD |
| 128 | TBD | TBD |

---

Expand All @@ -35,8 +51,8 @@ Run: `npm run benchmark:query-latency`

| Corpus size | Mean query latency (ms) |
|------------:|------------------------:|
| 100 pages | TBD |
| 500 pages | TBD |
| 100 pages | 20.16 |
| 500 pages | 369.45 |

Expected: latency grows sub-linearly because hotpath residents are scored
first and most queries are served without scanning the full corpus.
Expand All @@ -47,10 +63,10 @@ first and most queries are served without scanning the full corpus.

Run: `npm run benchmark:storage-overhead`

| Page count | Vector store size (bytes) | Bytes per page |
|-----------:|--------------------------:|---------------:|
| 50 | TBD | TBD |
| 200 | TBD | TBD |
| Page count | Read latency (ms) | Throughput (ops/s) |
|-----------:|-------------------:|-------------------:|
| 50 | 0.0014 | 732 003 |
| 200 | 0.0015 | 675 479 |

Expected: linear growth (no hidden quadratic allocations).

Expand All @@ -60,10 +76,10 @@ Expected: linear growth (no hidden quadratic allocations).

Run: `npm run benchmark:hotpath-scaling`

| Graph mass | H(t) capacity | Resident count | Promotion sweep (ms) |
|-----------:|--------------:|---------------:|---------------------:|
| 1 000 | ~22 | TBD | TBD |
| 5 000 | ~55 | TBD | TBD |
| Graph mass | H(t) capacity | Promotion sweep (ms) |
|-----------:|--------------:|---------------------:|
| 1 000 | ~22 | 0.09 |
| 5 000 | ~55 | 0.12 |

Invariant: Resident count never exceeds H(t).

Expand All @@ -73,5 +89,5 @@ Invariant: Resident count never exceeds H(t).

1. Run `npm run benchmark:all` on the target hardware.
2. Copy the `mean` column values from the Vitest bench output.
3. Replace every `TBD` cell in this file with the measured value.
3. Replace the measured cells in this file with the new values.
4. Commit with message `chore: update benchmark baselines — <hardware>`.
162 changes: 153 additions & 9 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,159 @@

## Table of Contents

1. [Core Data Types](#core-data-types)
2. [Storage Interfaces](#storage-interfaces)
3. [Vector Backends](#vector-backends)
4. [Embedding Backends](#embedding-backends)
5. [Model Profiles](#model-profiles)
6. [Routing Policy](#routing-policy)
7. [Hippocampus — Ingest API](#hippocampus--ingest-api)
8. [Cortex — Query API](#cortex--query-api)
9. [Daydreamer — Background Consolidation](#daydreamer--background-consolidation)
1. [Architecture Diagrams](#architecture-diagrams)
2. [Core Data Types](#core-data-types)
3. [Storage Interfaces](#storage-interfaces)
4. [Vector Backends](#vector-backends)
5. [Embedding Backends](#embedding-backends)
6. [Model Profiles](#model-profiles)
7. [Routing Policy](#routing-policy)
8. [Hippocampus — Ingest API](#hippocampus--ingest-api)
9. [Cortex — Query API](#cortex--query-api)
10. [Daydreamer — Background Consolidation](#daydreamer--background-consolidation)

---

## Architecture Diagrams

### Data Flow: Ingest Path

```
┌────────────┐
│ Raw Text │
└─────┬──────┘
┌─────────────────┐ maxChunkTokens from
│ Chunker.ts │◄── ModelProfile
│ (token-aware) │
└─────┬───────────┘
│ chunks: string[]
┌──────────────────────┐
│ EmbeddingRunner │──► resolves backend via ProviderResolver
│ (lazy init) │ (WebNN → WebGPU → WebGL → WASM → Dummy)
└─────┬────────────────┘
│ vectors: Float32Array[]
┌──────────────────────┐
│ PageBuilder.ts │──► SHA-256 content hash
│ (sign + hash) │──► Ed25519 signature
└─────┬────────────────┘
│ pages: Page[]
├─────────────────────────────────────┐
▼ ▼
┌──────────────┐ ┌───────────────────┐
│ VectorStore │ │ MetadataStore │
│ (OPFS) │ │ (IndexedDB) │
│ appendVector │ │ putPage / putBook │
└──────────────┘ └────────┬──────────┘
┌───────────────────┐
│ runPromotionSweep │
│ (hotpath update) │
└───────────────────┘
```

### Data Flow: Query Path

```
┌──────────────┐
│ Query Text │
└──────┬───────┘
┌──────────────────────┐
│ EmbeddingRunner │──► embed query text
│ (embedQueries) │
└──────┬───────────────┘
│ queryVector: Float32Array
┌──────────────────────────────────────────┐
│ Hotpath Scoring (fast path) │
│ • getHotpathEntries → resident pages │
│ • readVectors → dot product → top-K │
└──────┬───────────────────────────────────┘
│ hotpath results < topK?
┌──────────────────────────────────────────┐
│ Cold Path Scoring (fallback) │
│ • getAllPages → full corpus scan │
│ • readVectors → dot product → merge │
└──────┬───────────────────────────────────┘
│ merged top-K results
┌──────────────────────────────────────────┐
│ Side Effects │
│ • increment PageActivity.queryHitCount │
│ • runPromotionSweep (hotpath update) │
└──────┬───────────────────────────────────┘
┌────────────────┐
│ QueryResult │
│ { pages, │
│ scores, │
│ metadata } │
└────────────────┘
```

### Module Dependency Graph

```
┌─────────────────────────────┐
│ core/ │
│ types · ModelProfile │
│ HotpathPolicy · Salience │
│ crypto/ (hash, sign, verify)│
└──────────────┬───────────────┘
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────┐ ┌───────────────┐ ┌────────────────┐
│ embeddings/ │ │ storage/ │ │ VectorBackend │
│ EmbeddingBack │ │ VectorStore │ │ (WebGPU/GL/ │
│ EmbeddingRun │ │ MetadataStr │ │ NN/WASM) │
│ ProviderResol │ │ (OPFS, IDB) │ │ TopK │
└───────┬────────┘ └───────┬───────┘ └───────┬────────┘
│ │ │
└────────┬───────────┼─────────────────────┘
│ │
┌──────────▼───────────▼──────────┐
│ hippocampus/ │
│ Chunker · PageBuilder · Ingest │
│ HierarchyBuilder │
│ FastNeighborInsert │
└──────────────┬──────────────────┘
┌──────────────▼──────────────────┐
│ cortex/ │
│ Query · Ranking │
│ MetroidBuilder │
│ KnowledgeGapDetector │
│ OpenTSPSolver │
└──────────────┬──────────────────┘
┌──────────────▼──────────────────┐
│ daydreamer/ │
│ IdleScheduler │
│ HebbianUpdater │
│ PrototypeRecomputer │
│ FullNeighborRecalc │
│ ExperienceReplay │
│ ClusterStability │
└──────────────┬──────────────────┘
┌──────────────▼──────────────────┐
│ sharing/ │
│ CuriosityBroadcaster │
│ EligibilityClassifier │
│ SubgraphExporter/Importer │
│ PeerExchange │
└─────────────────────────────────┘
```

---

Expand Down
51 changes: 50 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ This guide covers building, testing, debugging, and contributing to CORTEX.
8. [VS Code Debugging (Electron)](#vs-code-debugging-electron)
9. [Docker Debug Lane](#docker-debug-lane)
10. [Model-Derived Numeric Guard](#model-derived-numeric-guard)
11. [Documentation Maintenance](#documentation-maintenance)
11. [Electron Runtime Gate Policy](#electron-runtime-gate-policy)
12. [Documentation Maintenance](#documentation-maintenance)

---

Expand Down Expand Up @@ -180,6 +181,54 @@ At the end of every implementation pass, update documents in this order:

---

## Electron Runtime Gate Policy

The Electron test lane enforces the following gate policy for GPU/graphics
requirements:

### GPU Requirements

| Capability | Required? | Notes |
|---|---|---|
| **WebGPU** | Optional | Preferred for vector operations and TransformersJs device; CI runners lack GPU access |
| **WebNN** | Optional | Preferred for ML inference; not available on most CI runners |
| **WebGL** | Required (software OK) | Minimum graphics capability; software-rendered via Xvfb in Docker |
| **WASM** | Required | Always-available compute fallback for vectors and embeddings |
| **OPFS** | Required | Origin Private File System for vector persistence |
| **IndexedDB** | Required | Metadata and hierarchy persistence |

### CI Gate Behaviour

- **Host-shell Electron** may crash with `SIGSEGV` in headless sandbox
environments that lack a GPU. This is **not** a blocking failure — use the
Docker lane instead.
- **Docker Electron lane** (`npm run docker:electron:up`) runs with Xvfb
software rendering. WebGL reports as available but WebGPU does not.
This lane is **not** a GPU-realism gate — it validates application startup,
IPC wiring, and storage initialisation.
- Set `CORTEX_ALLOW_ELECTRON_SKIP=1` to soft-skip the **full Electron runtime
tests** (driven by `scripts/run-electron-runtime-tests.mjs`, typically via
`npm run test:runtime`) when hardware is unavailable. The smoke-test runner
(`scripts/run-electron-runtime-smoke.mjs`, typically via
`npm run test:electron`) does **not** honor this variable and will still
fail if Electron is not installed or cannot start.
- The CI workflow does **not** run Electron tests by default. Full Electron
runtime tests are gated behind the `test:runtime` script and should be run
manually or in a dedicated GPU-enabled runner. The `test:electron` script
is a lightweight smoke test and remains a hard failure if Electron is
unavailable.

### Decision Matrix

| Environment | Electron tests run? | GPU available? | Expectation |
|---|---|---|---|
| Local (with GPU) | Yes | Yes | Full pass |
| Local (no GPU) | Skip full runtime tests (`CORTEX_ALLOW_ELECTRON_SKIP=1`) | No | Skip full harness gracefully; smoke tests may still fail without Electron |
| CI (ubuntu-latest) | No | No | Unit tests only |
| Docker lane | Yes (software render) | No | Startup + storage pass; WebGPU tests skipped |

---

## Hotpath Policy Constants Guard

To prevent hardcoded hotpath policy numeric literals (salience weights, tier
Expand Down
4 changes: 2 additions & 2 deletions sharing/SubgraphImporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function isValidPage(p: unknown): p is Page {
typeof page.pageId === "string" && page.pageId.length > 0 &&
typeof page.content === "string" &&
typeof page.embeddingOffset === "number" &&
typeof page.embeddingDim === "number" && page.embeddingDim > 0
typeof page.embeddingDim === "number" && page.embeddingDim > 0 // model-derived-ok
);
}

Expand Down Expand Up @@ -103,7 +103,7 @@ async function importNodes(
signature: "",
// Mark as "no local embedding yet"; downstream code can choose to re-embed.
embeddingOffset: 0,
embeddingDim: 0,
embeddingDim: 0, // model-derived-ok — sentinel: no local embedding yet
};

// Optionally verify that pageId matches SHA-256(content)
Expand Down
Loading
Loading