Metadata-Version: 2.4
Name: catalyst-brains
Version: 0.0.2
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Rust
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: License :: Other/Proprietary License
Requires-Dist: numpy>=1.22
Requires-Dist: cryptography>=42 ; extra == 'ed25519'
Provides-Extra: ed25519
License-File: LICENSE
Summary: Agent memory in fixed-size vectors: key-value recall with a confidence score, a positional cache, cause-effect memory, and a portable state file.
Author-email: Strategic Innovations AI <support@strategic-innovations.ai>
License: LicenseRef-Research-Eval
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# catalyst-brains

**A memory for AI agents that tells you, with every answer, how sure it is.**

catalyst-brains keeps what an agent learns in fixed-size vectors. A memory of 10,000 numbers holds a few hundred
associations, recalls one in under a millisecond on a laptop, and returns with each answer the score of the best
value and its lead over the next one. When the lead shrinks, the memory is getting full. You can see that before it
costs you, because the package predicts its own accuracy for the load you have put on it, and the prediction matches
measurement (table below).

```
pip install catalyst-brains
```

Python 3.9 or later. The core is compiled Rust; numpy is the only required dependency.

## Thirty seconds

```python
import catalyst_brains as cb

memory = cb.Memory(dim=10_000)
memory.train([("user:ana", "plan:pro"), ("user:ben", "plan:free"), ("user:cho", "plan:team")])

value, score, margin = memory.recall("user:ana")      # ("plan:pro", 0.58, 0.57)
memory.predicted_accuracy()                           # 1.0 at this load
```

Check your install from the command line:

```
python -m catalyst_brains
{"ok": true, "version": "0.0.2", "checks": {"bind_exact": true, "memory_recall": true}}
```

## What is in the package

| Part | What it does |
|---|---|
| `Memory` | Key-value pairs in one fixed-size state. `recall` returns value, score and margin; `predicted_accuracy()` and `health()` report how full it is. Training is one pass over your pairs, with no gradients. |
| `HoloKV` | A key-value cache with positions: recall a value by its key, or the value stored at a position. Early entries score the same as late ones. |
| `CausalMemory` | Records that one event led to another, with an optional time. Answers the effect of a cause and the causes of an effect, and keeps the direction: asking for the effect of an effect does not return its cause. |
| `Accumulator` | A running sum of angle vectors (the kind `random_phase` and `encode_scalar` return). Adding partial sums from separate workers gives exactly the state of one accumulator, byte for byte. |
| `BlockCode` | Binary vectors with XOR binding. A chain of 10,000 binds is undone exactly by the same chain. |
| `Resonator` | Recovers the parts of a combined vector when each part comes from a known list. |
| `encode_scalar` | Turns a number into an angle vector, so nearby numbers are similar and distant ones are not. |
| `rain` | A portable file and HTTP-header format for all of the above, checked with SHA-256 on load. Optional signed evidence records: HMAC-SHA256, or Ed25519 that anyone can verify with your public key. |
| `Ledger` and `catalyst-brains memory` | An append-only, hash-chained log for an agent's notes, with recall within a character budget, a hand-off summary, a doctor that finds edited rows, and a repair that backs up first and deletes nothing. |
| `MemoryUpdatePolicy` | Decides whether a new memory is accepted, consolidated first, or rejected, from novelty, confidence, saturation and evidence. |
| `ToolRegistry` | Keeps large tool schemas out of a model's context: a short paged list, and a search that expands a schema only when asked. It describes tools; it never runs them. |
| `vectors` | The primitives: `random_signs`, `random_phase`, `bind`, `majority`, `permute`, `similarity`. |
| `optimize.tsp` | Travelling-salesman tours with a Held-Karp lower bound, the gap between the two, and `optimal_proven` only when the bound meets the tour. An exact mode runs branch and bound up to 1,000 cities. Reads TSPLIB files. |
| `qubo` | Max-Cut and binary quadratic minimisation within a time budget. Every Max-Cut answer carries a certified upper bound. |

## Measured

Every number below was produced by `benchmarks/run.py` against the built wheel on 25 October 2026, on an Apple M1
Pro (macOS, arm64) with Python 3.11 and numpy 2.4. Run it yourself; it uses only the public API.

**Memory, 10,000 numbers, one distinct value per key.** Predicted is computed from the load before recall; measured
is the share of keys recalled correctly.

| Pairs stored | Predicted accuracy | Measured accuracy | Recall time |
|---|---|---|---|
| 100 | 1.000 | 1.000 | 0.09 ms |
| 200 | 1.000 | 1.000 | 0.17 ms |
| 400 | 0.971 | 0.973 | 0.31 ms |
| 800 | 0.634 | 0.638 | 0.62 ms |
| 1,600 | 0.204 | 0.195 | 1.21 ms |

Storing costs about 22 microseconds a pair. The state is 40 KB whatever the load. Recall time grows with the number of
distinct values the memory can answer with, not with the number of pairs.

**HoloKV, 10,000 numbers.** All 400 entries were recalled correctly both by key and by position. The first 50 stored
scored 1.02 on average and the last 50 scored 0.98. At 1,600 entries accuracy falls to 0.54 by key, and a query
takes 23 ms.

**CausalMemory.** The effect of each cause was right in 200 of 200 links, and in 68% of 800.

**Resonator, three lists, 4,096 numbers.** Exact for 40 of 40 trials at 1,000 combinations, 95% at 8,000, 82.5% at
64,000.

**Accumulator.** Splitting 64 items across 2 to 32 workers and adding the parts gave the serial state, byte for byte,
every time.

**rain.** A memory holding 500 pairs is a 40 KB state and an 11 KB `.rain` file. Writing it takes 3 ms; reading and
restoring it takes 0.2 ms.

**Ledger.** With 1,000 rows, recall for a prompt takes 35 ms and a full chain check takes 5 ms.

## Optimisation, measured

The TSP numbers come from `benchmarks/tsp.py` on 26 October 2026 (UTC), on the same M1 Pro, which other jobs were
sharing (load average 5.5 at the start). The instances are the 19 two-dimensional Euclidean TSPLIB instances of 51
to 1,002 cities, scored against their published optima. Distances use TSPLIB rounding, so lengths are comparable.

| Budget | Published optimum reached | Proven optimal by the solver | Bound below the optimum |
|---|---|---|---|
| 1 s | 16 of 19 | 6 of 19 | 0 to 6.4% (pr1002 widest) |
| 10 s | 19 of 19 | 7 of 19 | 0 to 2.8% (pr76 widest) |

With `exact=True` and 120 s each, branch and bound proved the optimum on 11 of the 13 instances of up to 200 cities:
eil51 in 0.08 s, kroA100 in 26 s, ch150 in 37 s, ch130 in 71 s. pr76 and kroA200 were not proven in 120 s; the
kroA200 tour was already optimal, and only the proof was missing. Over 5 seeds at 3 s, every instance from 200 to 442
cities reached its optimum on every seed; rat783 averaged 0.02% above it and pr1002 0.13%.

A first tour without a bound (`bound=False, time_limit=0`), on random cities, same run:

| Cities | Time (median of 4 warm calls) | Length above the Beardwood-Halton-Hammersley estimate of the optimum |
|---|---|---|
| 1,000 | 7.8 ms | 7.6% |
| 10,000 | 8.3 ms | 5.6% |
| 100,000 | 206 ms | 5.7% |

Give the search time if length matters.

**Max-Cut** (`benchmarks/maxcut.py`, 26 October 2026 UTC, load average 8.1): Gset G1 to G20, 800 vertices each,
10 s per instance, one thread, seed 1, against best-known cuts from arXiv:2606.03917 (Table S6). The solver came
within 1% of the best-known cut on 20 of 20 and equalled it on 13, with a median of 0.61 s to its best cut. A
simulated-annealing reference in the same package, given the same 10 s, also came within 1% on 20 and equalled 15;
head to head the solver was ahead on 3, level on 13 and behind on 4. The best-known cuts sit 3.8% to 20% below the
certified upper bound, so the bound proved none of them optimal.

## Know the limits before you build on it

- **A memory fills up.** Past a few hundred pairs per 10,000 numbers, accuracy falls, as the first table shows. Use
  `predicted_accuracy()` and the margin to decide when to start a new memory or raise `dim`.
- **Recall slows as the set of possible values grows**, because each candidate value is checked once: 2.4 ms at 3,200
  values for `Memory`, 23 ms at 1,600 for `HoloKV`.
- **The Resonator settles on wrong answers** once the combinations run into the tens of thousands at 4,096 numbers.
  Its confidence value shows when that has happened.
- **HMAC evidence can be forged by anyone who holds the secret.** For evidence someone else must trust, use the
  Ed25519 records (`pip install "catalyst-brains[ed25519]"`).
- **The TSP solver handles one symmetric tour.** No time windows, capacities or multiple vehicles; asymmetric
  matrices are refused. Proofs can take minutes past 100 cities and may not finish, and with `bound=True` the gap is
  only as good as the bound, which is loose at 1,000 cities and a one-second budget.
- **Max-Cut and QUBO answers are heuristic.** The Max-Cut bound is certified but loose (see above), so it rarely
  proves an answer optimal. QUBO results carry no bound at all.
- **Nothing here runs on a GPU**, and nothing here sends data anywhere unless you call `catalyst_brains.client`.
- **Wheels:** macOS (Apple silicon and Intel) and Linux (x86_64 and aarch64, glibc 2.17 or later), each tested
  from its own wheel before release. Windows and Alpine (musl) are not built yet, and there is no source
  distribution.

## Coming from catalyst-brain 1.x

The 0.0.x line is a new implementation, not an upgrade, and it installs alongside 1.x without conflict.

| 1.x | 0.0.2 |
|---|---|
| `import catalyst_hdc` | `from catalyst_brains import vectors` |
| `rand_bipolar`, `resonance` (0 to 1) | `random_signs`, `similarity` (-1 to 1); `similarity01` keeps the old scale |
| `hdc_bind`, `hdc_bundle`, `hdc_permute` | `bind`, `majority`, `permute` |
| `PyHoloCPUScheduler.recall` (a lookup table) | `Memory.recall`, which returns value, score and margin |
| `PyHKVC` (a lookup table) | `HoloKV` |
| `PyCausalMemory` | `CausalMemory` |
| `RainPayload`, `rain_dumps`, `rain_loads` | `rain.RainPayload`, `rain.dumps`, `rain.loads` (format version 3) |
| `MemoryUpdatePolicy`, `CatalystTokenKernel` | `MemoryUpdatePolicy`, `ToolRegistry` |

Not carried over:
- **The graphics encoders and the self-audit classes.** The audit passed any input.
- **The Hugging Face cache adapters.** We do not have model-level evidence for them yet.
- **Local Python execution in the tool kernel.** A memory library should not run code.
- **Telemetry.**

## Command line

```
catalyst-brains memory --ledger ~/.catalyst-brains/brain.jsonl --agent-id my-agent --json pulse --domain ops --book "Never deploy from a dirty tree" "Deployed 0.4.2"
catalyst-brains memory --ledger ~/.catalyst-brains/brain.jsonl --json inject --limit 3 --max-chars 1200 "how do we deploy"
catalyst-brains memory --ledger ~/.catalyst-brains/brain.jsonl --json doctor
catalyst-brains memory --ledger ~/.catalyst-brains/brain.jsonl --json repair --backup brain.bak
catalyst-brains memory --ledger ~/.catalyst-brains/brain.jsonl --json compact --recent 5 --max-chars 1200
```

## Licence

Free for research, evaluation, benchmarks and prototypes. Production systems, hosted services, redistribution and
resale need written permission from Strategic Innovations AI: sales@strategic-innovations.ai. Support:
support@strategic-innovations.ai.

