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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
},
"metadata": {
"description": "Honeycomb — persistent memory daemon and thin harness clients for AI coding assistants",
"version": "0.22.0"
"version": "0.22.1"
},
"plugins": [
{
"name": "honeycomb",
"description": "Honeycomb Claude Code plugin — captures session activity and provides cross-session memory through the local daemon",
"version": "0.22.0",
"version": "0.22.1",
"source": "./harnesses/claude-code"
}
]
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "honeycomb",
"description": "Honeycomb — a long-lived daemon plus thin clients for six coding harnesses, the unified honeycomb CLI, the MCP server, and the embed daemon",
"version": "0.22.0",
"version": "0.22.1",
"author": {
"name": "Honeycomb"
},
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v0.22.1 — 2026-10-04

Internal documentation/knowledge-base updates clarifying how memory lifecycle, pipeline, graph, and retrieval features actually behave versus prior docs; no functional code changes shipped.

## v0.22.0 — 2026-07-14

Honeycomb's CLI now speaks a standardized command interface with new restart, service-install, service-uninstall, register, logs, and JSON-envelope automation support, plus safer service update/uninstall flows with health-checked rollback. Existing daemon commands remain fully backward compatible.
Expand Down
2 changes: 1 addition & 1 deletion harnesses/claude-code/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "honeycomb",
"description": "Honeycomb — persistent memory for Claude Code sessions via the local Honeycomb daemon",
"version": "0.22.0",
"version": "0.22.1",
"author": {
"name": "Honeycomb"
},
Expand Down
2 changes: 1 addition & 1 deletion harnesses/codex/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "honeycomb-codex",
"version": "0.22.0",
"version": "0.22.1",
"description": "Honeycomb — persistent shared memory for OpenAI Codex CLI via the local Honeycomb daemon",
"type": "module",
"license": "AGPL-3.0-or-later"
Expand Down
2 changes: 1 addition & 1 deletion harnesses/openclaw/openclaw.plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@
}
}
},
"version": "0.22.0"
"version": "0.22.1"
}
2 changes: 1 addition & 1 deletion harnesses/openclaw/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "honeycomb-openclaw",
"version": "0.22.0",
"version": "0.22.1",
"type": "module",
"description": "Honeycomb — persistent shared memory for AI agents, OpenClaw harness",
"license": "AGPL-3.0-or-later",
Expand Down
22 changes: 14 additions & 8 deletions library/knowledge/private/ai/distillation-and-tier1-keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ flowchart LR
inherits the grounding.

Honeycomb's current summary worker (PRD-017) shells out to the *host agent's CLI* with a gate prompt
(no API key of its own; secrets scrubbed first). That is a fine execution model; the change this
strategy asks for is the *prompt discipline* (structured-extraction-first) layered on top, plus the
extra key-derivation step.
(no API key of its own; secrets scrubbed first). That execution model is what runs today. The live
gate already emits `{ extraction, summary, key }` in that order (`src/daemon/runtime/summaries/key.ts`),
and the worker writes `key` on the `memory` row (`src/daemon/runtime/summaries/worker.ts`). The
structured-extraction-first discipline and the key-derivation step are the path the worker runs.

---

Expand All @@ -105,9 +106,12 @@ source: Tier-2 distillation is implemented, shipped, and now running in the live
> unit + live itests; all CI gates green; security passed first). 017a generates a per-session
> summary via the host-CLI gate and writes a `memory` row at `/summaries/<userName>/<sessionId>.md`
> with `summary` + a short `description` + a (non-fatal) embedding; 017b synthesizes a top-level
> `/MEMORY.md` linking those summaries. It is **not a stub**: the `notImplemented` reference lingering
> in `summaries/index.ts`'s *header comment* is stale; the file body exports the real
> `synthesizeMemoryIndex` / `synthesizeThreadHeads`.
> `/MEMORY.md` linking those summaries. The synthesis functions are **not a stub**:
> `synthesizeMemoryIndex` and `synthesizeThreadHeads` are implemented in
> `src/daemon/runtime/summaries/synthesis.ts` and exported from
> `src/daemon/runtime/summaries/index.ts`. The barrel *header* still calls 017b an honest stub.
> It does not mention `notImplemented`. `notImplemented` is still a live export of that barrel
> (defined in `src/daemon/runtime/summaries/contracts.ts`).

What was once the gap, "built but not assembled", is now closed:

Expand All @@ -130,8 +134,10 @@ columns the summary gate now populates rather than generating keys at read time.
Honeycomb already runs two distillation loops that the key generator should mirror rather than
duplicate:

- **The summary worker** (`memory` summaries, PRD-017, built + `Completed`), the natural home for
Tier-2 + key derivation once the worker is wired live. See [`wiki-summary-workers.md`](wiki-summary-workers.md).
- **The summary worker** (`memory` summaries, PRD-017, built + `Completed`), the live home for
Tier-2 summaries and the `key` written on the memory row. The summary job worker is built in
`src/daemon/runtime/assemble.ts` and writes keys in `src/daemon/runtime/summaries/worker.ts`.
See [`wiki-summary-workers.md`](wiki-summary-workers.md).
- **The skillify gate** (sessions → `SKILL.md`, a Haiku KEEP/MERGE/SKIP verdict), proof that
Honeycomb already distills sessions into compact, judged artifacts with provenance. The Tier-1 key
is a lighter sibling of a skill: "one sentence that indexes a memory" vs "a reusable lesson." See
Expand Down
34 changes: 20 additions & 14 deletions library/knowledge/private/ai/graphrag-followon.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ GraphRAG is the mechanism for that minority of queries. It is a *follow-on*, not

---

## 2. The design (transferable from the prior art)
## 2. The design (prior-art template)

Owl's Roost's GraphRAG is a clean, Postgres-native template that maps directly onto Honeycomb's
SQL+vector store:
Owl's Roost's GraphRAG is a Postgres-native template. Its hop walk is a recursive CTE. Honeycomb's
daemon has no `WITH RECURSIVE` under `src/daemon`. Deep Lake does not run that Postgres hop walk.
GraphRAG stays approved and unbuilt. The diagram below is the prior-art shape a later PRD would
have to reimplement:

```mermaid
flowchart TD
Q["agent query"] --> V["vector recall (top-K candidates)"]
Q --> E["find entities (lexical / FTS on entity text)"]
E --> T["traverse graph (recursive CTE, 2 hops, cycle-safe)"]
E --> T["prior-art hop walk (recursive CTE; not in this daemon)"]
V --> F["RRF fuse (vector results + graph chains)"]
T --> F
F --> R["rerank top-N"]
Expand All @@ -53,12 +55,14 @@ flowchart TD
INSIGHT / OUTCOME / GOAL).
- **Relationships** are typed, weighted edges: RESOLVES, LEADS_TO, BUILDS_ON, CONTRADICTS,
SIMILAR_TO, TRIGGERED_BY (again, the prior art's set, fit to code work).
- **Traversal** is a recursive CTE (2-3 hops) with cycle detection, Postgres handles a sparse graph
(hundreds of nodes per repo) without a dedicated graph DB.
- **Fusion** reuses the *same RRF* the recall engine already uses (vector list + graph-chain list,
`k = 60`), so graph results compose with the existing retrieval rather than replacing it.
- **Traversal** in the prior art is a recursive CTE (2-3 hops) with cycle detection. That statement
describes Postgres. This daemon does not issue `WITH RECURSIVE`, and there is no GraphRAG extractor
or hop walker. A follow-on cannot assume the store already walks a sparse graph.
- **Fusion** can reuse the *same RRF* the recall engine already uses (`RRF_K = 60` in
`src/daemon/runtime/memories/recall.ts`). That constant exists. A graph-chain list feeding it does not.

This is deliberately the prior art's architecture, it is proven and it fits.
The entity and relationship vocabulary above is the prior art's architecture. The fusion constant is
the piece already in this tree.

---

Expand All @@ -67,9 +71,10 @@ This is deliberately the prior art's architecture, it is proven and it fits.
Honeycomb does not start from zero on graph, which is a large part of why the follow-on is reasonable:

- **A knowledge-graph table substrate already exists.** Honeycomb has graph entity/relationship
tables (`USING deeplake`) with typed nodes, weighted edges, and even `content_embedding` columns;
see [`knowledge-graph-ontology.md`](knowledge-graph-ontology.md). GraphRAG would *populate and
traverse* this, not invent it.
tables (`USING deeplake`) with typed nodes, weighted edges, and `content_embedding` on the graph
catalog (`src/daemon/storage/catalog/knowledge-graph.ts`); see
[`knowledge-graph-ontology.md`](knowledge-graph-ontology.md). GraphRAG would *populate and
traverse* this. The tables are not a recursive hop walker.
- **A codebase graph already exists.** The tree-sitter codebase extractor builds a file/symbol/import
graph into a `codebase` table (content-addressed cache). That is a second, code-structural graph the
relational memory can lean on (e.g. "this decision touched these symbols").
Expand Down Expand Up @@ -102,8 +107,9 @@ proves itself, and built behind the same eval discipline that governs everything
## 5. Author's note (no strong disagreement)

For the record, the design discussion did not surface a strong objection to building GraphRAG as a
follow-on, the substrate exists, the architecture is proven, and AI-assisted build cost is low. The
only caution carried forward is the sequencing-and-measurement one above: ship and measure the 3-tier
follow-on. The table substrate, `content_embedding`, the codebase graph, and `RRF_K = 60` exist.
The recursive-CTE hop walk does not, so the follow-on still has to specify traversal. The other
caution carried forward is the sequencing-and-measurement one above: ship and measure the 3-tier
prime first, then build the graph against a demonstrated relational gap. When that PRD is written,
this doc is its design brief.

Expand Down
45 changes: 27 additions & 18 deletions library/knowledge/private/ai/hybrid-sql-vector-rationale.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Why Hybrid (SQL + Vector) Makes the Zoom Memory Doable

> Category: Ai | Version: 1.1 | Date: June 2026 | Status: Active
> Category: Ai | Version: 1.2 | Date: October 2026 | Status: Active

Why Honeycomb's Deep Lake substrate (SQL *and* vector in one store) is a genuinely better fit for the
3-tier zoom memory than a vector-only store, and what each half of the hybrid is responsible for.
Expand Down Expand Up @@ -32,7 +32,7 @@ right?"*, is correct.
```mermaid
flowchart TD
A["① Skim the index<br/>(prime: recent + durable keys)"] --> SQLa["lexical + recency<br/><b>SQL</b>, cheap, deterministic"]
B["② Resolve a key<br/>(key → summary → raw)"] --> SQLb["join by id / path<br/><b>SQL</b>, exact lookup"]
B["② Resolve a key<br/>(key → summary → raw)"] --> SQLb["lookup by id<br/><b>SQL</b>, exact"]
C["③ Mine for memory<br/>(search you didn't know to name)"] --> VEC["semantic cosine + lexical, fused<br/><b>Vector + SQL (RRF)</b>"]
```

Expand All @@ -41,7 +41,7 @@ flowchart TD
timestamp plus a keyword/lexical filter, a cheap SQL query with **no embedding cost**. You do not
pay vector search to render a table of contents.
2. **Resolve a key (the zoom).** `key → summary → raw` is "fetch the row this id points to, then the
`sessions` rows for that session." That is a **deterministic join by id/path**. It is the single
`sessions` rows for that session." That is a **deterministic SQL lookup by id**. It is the single
most important property in this whole strategy, and it is exactly what SQL is for.
3. **Mine (the search).** When the agent looks for memory it did not see in the index, semantic
similarity matters, this is the `<#>` cosine vector path, fused with the lexical arm via RRF. This
Expand All @@ -61,9 +61,12 @@ The zoom hierarchy lives or dies on cheap, exact resolution. Consider the differ
its summary and then its raw turns, you store relationship ids in each point's *payload* and issue
follow-up filtered lookups. It works, but you are using a similarity engine to do a key-value join,
and every step is a separate filtered scan.
- **Deep Lake (SQL+vector):** resolution is a `SELECT … WHERE path = '<id>'` (and the raw turns are
`SELECT … FROM sessions WHERE path = '<session>'`). The id *is* the join key. The same store that
holds the embeddings answers the join.
- **Deep Lake (SQL+vector):** depth 1 is a guarded select of `memory.summary` or `memories.content`
by path or id. Depth 2 does not match `sessions.path` to the summary path. Capture stores the
transcript path on `sessions.path` and the session identity in `sessions.id`, so depth 2 uses
`id LIKE 'sess-<sessionId>-%'` plus a post-filter (`src/daemon/runtime/memories/resolve.ts`).
`GET /api/memories/resolve` is the route; `hivemind_read` calls it. The same store that holds the
embeddings answers the lookup.

Because the tiers already live in three SQL tables (`memories`, `memory`, `sessions`) keyed by
`id`/`path`, the resolve chain is *already expressible*, it's the existing read path
Expand All @@ -76,7 +79,7 @@ Because the tiers already live in three SQL tables (`memories`, `memory`, `sessi
| Concern | Engine | Why |
|---|---|---|
| Prime digest (Tier-1 index) | **SQL** (lexical `ILIKE` + recency `ORDER BY`) | Cheap, deterministic, no embedding cost; runs every session |
| Resolve key → summary → raw | **SQL** (join by `id`/`path`) | Exact lookup; the zoom is a pointer walk, not a search |
| Resolve key → summary → raw | **SQL** (lookup by id; depth 2 is a session-id prefix) | Exact lookup; the zoom is a pointer walk |
| Mine (agent-initiated search) | **Vector + SQL, fused (RRF)** | Semantic recall for the unnamed; lexical arm catches exact tokens |
| Scope / tenancy filter | **SQL** (org / workspace / agent) | Already enforced on every query in `recall.ts` |

Expand All @@ -90,17 +93,22 @@ index, the resolution, the scoping, is SQL. That is the efficiency argument for
A grounded caveat for any future agent, because it was settled with live measurement this cycle:

- **The mining path uses post-query Reciprocal-Rank Fusion (RRF), and it works.** `recall.ts` runs a
`<#>` semantic arm and a BM25/`ILIKE` lexical arm per table and fuses their ranked lists with RRF
(`RRF_K = 60`, arm-class weights distilled `memory` 1.0 / raw `session` 0.4). Measured live:
recall@5 ≈ 0.72-0.78.
- **Deep Lake's *native* `deeplake_hybrid_record` operator does NOT work for us and must not be used.**
Benchmarked live, it returns a constant `0` score for every row (degenerate ordering → near-random
recall@5 ≈ 0.14-0.17), independent of weight or vector-literal format. PRD-047a closed with "keep
RRF." Full report: [`deeplake-hybrid-record-operator-report.md`](deeplake-hybrid-record-operator-report.md).

So "hybrid" here means **SQL for structure + vector for similarity, fused in our own RRF**, *not* the
DB's native hybrid operator. A future agent that reads "hybrid" must not reach for
`deeplake_hybrid_record`; it is filed as a vendor bug, not a tool.
`<#>` semantic arm and a tokenized `ILIKE` lexical arm per table (`buildLexicalMatchSql`; Deep Lake
`deeplake_index` is unwired) and fuses their ranked lists with RRF (`RRF_K = 60`, arm-class weights
distilled `memory` 1.0 / raw `session` 0.4). The 2026-06-22 live band was recall@5 ≈ 0.72-0.78.
The 2026-06-24 re-run measured RRF recall@5 at 0.611.
- **Heavy path and per-turn path split on the memories semantic arm.** The heavy path still runs
`<#>` through `vectorSearch`. The per-turn path (`fast: true`) serves the `memories` semantic arm
from `InMemoryLocalVectorIndex` when the index is ready. Sessions and hive semantic SQL, and every
lexical arm, still run.
- **Deep Lake's native `deeplake_hybrid_record` operator stays unwired.**
`src/daemon/runtime/memories/hybrid-recall.ts` exports `hybridRecall` and has no other `src/`
importer. The 2026-06-22 run returned a constant `0` score (recall@5 ≈ 0.14-0.17). The 2026-06-24
re-run is parity with RRF (recall@5 0.611 vs 0.611). Parity is not a win, so RRF stays the default.
Full report: [`deeplake-hybrid-record-operator-report.md`](deeplake-hybrid-record-operator-report.md).

So "hybrid" here means **SQL for structure + vector for similarity, fused in our own RRF**. The native
operator is a revisit candidate, recorded in the operator report and ADR-0001.

---

Expand All @@ -120,3 +128,4 @@ is *more* doable than the prior system it is modeled on, the owner's intuition i
|------|---------|--------|
| 2026-06 | 1.0 | Initial rationale for the SQL+vector division of labor; grounded in the PRD-047a operator finding. |
| 2026-06 | 1.1 | Core shipped (PRD-046, merged #77); status normalized to Active; recall numbers and the native-operator finding reconciled with the live A/B. |
| 2026-10 | 1.2 | Recall numbers dated to the 2026-06-22 band and the 2026-06-24 tie. Lexical arm named as tokenized ILIKE. Depth-2 resolve is a session-id prefix. Per-turn memories semantic arm can come from the local index. |
Loading
Loading