activeloopai / activeloopai/hivemind

Silent capture loss when target workspace/table is unreachable or has a stale schema

未關閉
#84 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
主要語言
TypeScript
星號
1.6k
分支
107
平均合併
17 小時 30 分鐘
30 天內合併 PR
6

描述

## Problem

When the workspace selected by `~/.deeplake/credentials.json` (or `HIVEMIND_WORKSPACE_ID`) routes the capture INSERT to a `sessions` table that the hook cannot write to — wrong workspace, missing column, revoked permission, body-size cap — **the capture is dropped silently**. The host agent (Claude Code, Codex, Cursor, Hermes) gets no signal, the user sees no warning, and every tool call/prompt/response in that session is lost from memory.

## How we hit it today

While testing Phase 1 embedding work I switched the active org to `test_plugin/default`. That workspace has a legacy `sessions` table with a schema that predates the `agent` column. Every PostToolUse INSERT then failed with one of:

- `403 Forbidden` (write blocked by ACL on a foreign workspace)
- `Column does not exist: column "agent" does not exist` (legacy schema)

The hook caught the error, ran `await api.ensureSessionsTable(sessionsTable)` (a no-op `CREATE TABLE IF NOT EXISTS` because the table already exists at the old schema), retried the INSERT, failed again, then `throw e` → caught by the outer `main().catch(...)` → `process.exit(0)`. From the host's POV the hook returned cleanly. From the DB's POV no row landed. Side-effect: the host's tool-call wrapper saw a non-zero status from somewhere in the hook chain and started returning exit code 144 on every Bash call until the org was switched back — confusing and unrelated-looking.

## Evidence

- 0 captured rows in the destination table during the broken window
- `~/.deeplake/hook-debug.log` (only available when `HIVEMIND_DEBUG=1` is set) shows the real error:

```
2026-05-01T06:34:49.802Z [sdk] query fail (3950ms): INSERT INTO "sessions_ide_test" ... :: Query failed: 403: 403 Forbidden...
2026-05-01T06:34:49.802Z [cursor-capture] fatal: Query failed: 403: ...
```

- Without `HIVEMIND_DEBUG=1` the user gets nothing — no stderr line, no status banner, no surfaced count of dropped rows.

## Why it's bad

Hivemind's whole value prop is \"never lose a session.\" A misconfigured workspace today degrades us to silently-zero capture. Users only notice when they ask their agent to `grep ~/.deeplake/memory/` weeks later and find nothing.

## Repro

1. Have an org/workspace with a legacy `sessions` table missing the current schema (e.g. no `agent` column), or where the API token lacks INSERT permission.
2. Point `~/.deeplake/credentials.json` (or `HIVEMIND_*` env) at it.
3. Run any Claude Code / Codex / Cursor / Hermes tool call.
4. Inspect destination table → no row. Inspect hook stderr / agent transcript → no warning. The only signal is `~/.deeplake/hook-debug.log` if `HIVEMIND_DEBUG=1` happens to be set.

## Proposed mitigations (non-binding, pick one or several)

1. **Surface the first capture failure to the host.** Once per session, write one short stderr line from the hook (`hivemind: capture INSERT failed (403 Forbidden) — see ~/.deeplake/hook-debug.log`). Claude Code and Codex pipe hook stderr into the transcript by default, so this becomes visible without breaking the \"don't block the agent\" contract.
2. **Persist a per-session failure counter** to a small file under `~/.deeplake/` and emit a warning at SessionEnd if any captures were dropped (`hivemind: 27 captures lost this session due to repeated 403 — check workspace/credentials`).
3. **Schema preflight at SessionStart**, similar to the existing `ensureEmbeddingColumn`: if the `sessions` table exists but is missing required columns, log a hard warning to stderr and abort capture for the session (better dead-loud than dead-silent).
4. **`hivemind status` should include a \"recent capture errors\" line** sourced from the debug log so users can see drift without setting `HIVEMIND_DEBUG=1` first.

## Notes

- The error-classifier substring check (`includes(\"permission denied\") || includes(\"does not exist\")`) is what triggers the no-op retry on schema-mismatch errors. Worth tightening so a column-not-exist error doesn't get mistaken for a table-not-exist error.
- The 144 exit-code side-effect on the host's Bash wrapper deserves its own follow-up — investigate whether a hook subprocess error is leaking back through Claude Code's tool-call stack.

貢獻指南

這個儲存庫沒有索引到貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。