* feat: add optional LiteLLM SDK embedding output dimensions
Allow configuring an optional output dimension for litellm-sdk embeddings and pass it through only when set, while preserving default behavior.
Made-with: Cursor
* test: assert wrapped init error for invalid dimensions
Add a LiteLLM SDK embeddings test that verifies invalid OpenAI dimensions fail during initialize() and preserve provider error details in the wrapped RuntimeError.
Made-with: Cursor
* feat: expose document_metadata in API and control plane
Add document_metadata (sourced from retain_params.metadata) to both
list and get document endpoints. Display it in the control plane
documents table and detail panel. Drop the unused metadata column
from the documents table (was always stored as empty {}).
* fix: code review fixes for document_metadata feature
- Remove unnecessary `import json as _json` (json already imported at module level)
- Simplify redundant truthiness checks in retain_params parsing
- Regenerate OpenAPI spec and client SDKs (Python, TypeScript, Go)
- Add tests for document_metadata in get_document and list_documents
* feat(ui): improve documents table and detail panel
- Relative timestamps with full date on hover
- Remove context column from table
- Metadata shown as k=v badges (blue, like tags)
- Size in bytes instead of chars
- Document IDs wrap instead of truncating
- Detail panel wider (560px)
- Retain params: context, event_date, metadata badges
* feat: add /code-review skill for automated code quality checks
Adds a Claude Code skill that reviews changes against project standards:
missing tests, dead code, type safety, lint, and CLAUDE.md conventions.
CLAUDE.md now instructs contributors to run /code-review after implementation.
* refactor: move code standards from CLAUDE.md into /code-review skill
Single source of truth for coding conventions (Python style, type safety,
TypeScript style) is now .claude/skills/code-review.md. CLAUDE.md points
to the skill for reading before coding and running after implementation.
* feat: add code comments convention to /code-review skill
Require comments explaining non-trivial technical decisions, with history
of previous approaches. Review step checks for missing reasoning comments,
stale comments, and undocumented approach changes.
* fix: move skill to directory structure for Claude Code discovery
Claude Code requires .claude/skills/<name>/SKILL.md, not loose .md files.
* feat: add branch hygiene checks to /code-review skill
Review step 1 now verifies branch is based on recent origin/main and
all commits are relevant to the feature. Unrelated commits flagged as
must-fix.
* feat: strengthen code review rules and fix stale CLAUDE.md references
- Enforce no multi-item tuple returns and no raw dicts even for internal code
- Add mandatory /code-review gate before push/PR
- Add integration completeness checklist (tests, CI job, release-integration.sh)
- Fix stale references: remove hindsight/ dir, update integrations list,
update LLM providers, remove hardcoded file sizes, fix _HIERARCHICAL_FIELDS
-> _CONFIGURABLE_FIELDS
* docs: add ./scripts/dev/start.sh for local dev in CLAUDE.md
* feat(api): warn on unknown request parameters via X-Ignored-Params header
Add middleware that detects unknown query params and JSON body fields,
logs a server-side warning, and returns an X-Ignored-Params response
header listing the ignored parameters. This surfaces silent parameter
ignoring (e.g. tag=source:slack on /memories/list) without breaking
forward compatibility between client and server versions.
Closes#792
* ci: report safe-to-test CI results on PR via status and comment
pull_request_target workflow runs are not linked to the PR by GitHub,
so the CI results are invisible on the PR page after adding safe-to-test.
Add a report-pr-status job that:
- Creates a commit status on the PR head SHA
- Posts/updates a summary comment with pass/fail counts and failed job names
* ci: skip secret-dependent jobs on fork pull_request events
Adds a has_secrets output to detect-changes that is false for fork PRs
via pull_request events. All 15 secret-dependent jobs now check this
output before running, avoiding guaranteed failures on fork PRs.
Fork contributors will see these jobs as skipped instead of failed,
and can use the safe-to-test label to run the full CI suite.
Add middleware that detects unknown query params and JSON body fields,
logs a server-side warning, and returns an X-Ignored-Params response
header listing the ignored parameters. This surfaces silent parameter
ignoring (e.g. tag=source:slack on /memories/list) without breaking
forward compatibility between client and server versions.
Closes#792
* feat: add /code-review skill for automated code quality checks
Adds a Claude Code skill that reviews changes against project standards:
missing tests, dead code, type safety, lint, and CLAUDE.md conventions.
CLAUDE.md now instructs contributors to run /code-review after implementation.
* refactor: move code standards from CLAUDE.md into /code-review skill
Single source of truth for coding conventions (Python style, type safety,
TypeScript style) is now .claude/skills/code-review.md. CLAUDE.md points
to the skill for reading before coding and running after implementation.
* feat: add code comments convention to /code-review skill
Require comments explaining non-trivial technical decisions, with history
of previous approaches. Review step checks for missing reasoning comments,
stale comments, and undocumented approach changes.
* fix: move skill to directory structure for Claude Code discovery
Claude Code requires .claude/skills/<name>/SKILL.md, not loose .md files.
* feat: add branch hygiene checks to /code-review skill
Review step 1 now verifies branch is based on recent origin/main and
all commits are relevant to the feature. Unrelated commits flagged as
must-fix.
Fork PRs don't have access to repository secrets, so integration tests
that need API keys (GCP, OpenAI, Cohere, etc.) are skipped. Maintainers
can now add the `safe-to-test` label after reviewing fork PR code to
trigger the full test suite with secrets via pull_request_target.
Follow-up to #764. Upgrades the silent debug log in waitForReady to
log.warn so unexpected calls before service.start() are visible, and
adds tests covering the CLI mode no-op path.
OpenClaw loads plugins on every CLI command (status, models auth add,
config validate, etc.), not just gateway start. The plugin was starting
LLM detection, daemon initialization, and API health checks immediately
in the default export, causing unnecessary resource usage and terminal
noise on routine CLI operations.
Move all heavy initialization (detectLLMConfig, embedManager.start(),
checkExternalApiHealth, client creation) into service.start() which is
only called when the gateway starts. The default export now only does
lightweight config parsing and service/hook registration.
Hooks (before_prompt_build, agent_end) gracefully no-op when called
before service.start() via the waitForReady guard.
Closes#746
* fix(engine): classify first-person agent experiences as 'experience' fact type
The extraction prompt defined "assistant" too narrowly as only "interactions
with assistant (requests, recommendations)", causing the LLM to classify
first-person agent actions (code changes, debugging, discoveries) as "world".
Broadened the fact_type definition in the prompt and Pydantic model descriptions
to cover all first-person actions, experiences, and observations by the speaker.
* style: fix line length in fact_extraction.py
The installer skipped settings.json entirely if it already existed,
leaving version and new config keys stale. Now merges: updates version,
adds new upstream keys, preserves user customizations.
Also fixes pre-existing typo: RERANK_URL → rerank_url in ZeroEntropy
cross-encoder.
* SEO: add title and description to all integration pages
All 17 integration docs pages were missing title and description
frontmatter, causing Docusaurus to generate unhelpful titles like
"OpenClaw | Hindsight" and pull body text as meta descriptions.
- Add keyword-rich title and description frontmatter to all integration
pages in both docs/ (current) and versioned_docs/version-0.4/
- Add scripts/check-integration-seo.mjs to enforce title + description
on all future integration pages
- Wire the check into the build script so it runs locally and in CI
* Fix missing frontmatter on docs/sdks/integrations/openclaw.md
* Regenerate docs skill after integration page SEO updates
- Retitle to match search intent: "How to Add Persistent Memory to
OpenClaw with Hindsight" targets openclaw memory/persistent memory queries
- Add intro paragraph before <!-- truncate --> so Docusaurus generates a
proper meta description instead of "TL;DR"
- Expand tags from [openclaw] to include memory, agents, persistent-memory,
knowledge-graph
* fix(llamaindex): use uuid for document_id and sync version metadata
- Replace timestamp-based document_id with uuid4 hex to prevent
collisions on rapid retains (timestamp_ms can duplicate in tight loops)
- Sync __version__ in __init__.py to match pyproject.toml (0.1.2)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): pass memory to run() instead of ReActAgent constructor
LlamaIndex 0.14.x ReActAgent does not accept a memory parameter in
its constructor — it's silently dropped via **kwargs. Memory must be
passed to agent.run(memory=...) where AgentWorkflow picks it up.
Also fixes the undefined `tools` variable (now `tools=[]`).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(llamaindex): strip ReAct reasoning traces from retained assistant messages
HindsightMemory.put/aput now extracts only the final Answer: text from
assistant messages containing ReAct reasoning (Thought:/Action:/Observation:
prefixes), preventing internal reasoning traces from polluting long-term memory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(llamaindex): fix docstring example to pass memory to run()
The HindsightMemory class docstring showed the broken pattern of passing
memory= to the ReActAgent constructor, which silently drops it. Updated
to show the correct pattern: pass memory to agent.run().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Document the new configurable base URL for the ZeroEntropy reranker
provider added in #766. Also fix a type error where RERANK_URL was
renamed to rerank_url but one usage was missed.
The automatic memory example referenced an undefined `tools` variable.
Since HindsightMemory handles retain/recall transparently, no tools
are needed — use an empty list.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes#771 — two trailing commas in openclaw.plugin.json caused OpenClaw's
strict JSON parser to reject the plugin manifest during installation.
Also adds JSON validation tests for both the openclaw plugin manifest and
the claude-code hooks.json so CI catches invalid JSON before release.
* refactor(llamaindex): merge two packages into single hindsight-llamaindex
Merge `llama-index-tools-hindsight` and `llama-index-memory-hindsight` into
a single `hindsight-llamaindex` package following our naming convention.
- Rename package to `hindsight-llamaindex` (Python module: `hindsight_llamaindex`)
- Move HindsightToolSpec and HindsightMemory into the same package
- Delete `llamaindex-memory/` directory
- Add CI test job for llamaindex integration
- Update docs, blog post, and integrations.json
* fix(blog): update llamaindex blog post for merged package
- Move date to 2026-03-30
- Add HindsightMemory (automatic BaseMemory) pattern
- Fix "bank must exist first" pitfall — mission auto-creates
- Align all code examples with docs page
- Update architecture diagram to show both patterns
* fix(docs): add llamaindex/openai icons, rename Codex
- Add llamaindex.png and openai.png icons
- Rename "OpenAI Codex CLI" to "Codex" in integrations.json and docs
- Use openai.png icon for Codex integration
* feat(api): add duration_ms to audit log entries
Server-computed duration in milliseconds (started_at → ended_at) on
the list audit logs endpoint. Null when ended_at is not set.
Closes#749
* feat(api): add duration_ms to audit log entries and type audit endpoints
- Add server-computed duration_ms (started_at → ended_at) to audit log
list response. Null when ended_at is not set.
- Add typed Pydantic response models for both audit log endpoints
(list and stats) so they appear in the OpenAPI spec.
- Regenerate OpenAPI spec and all client SDKs.
Closes#749
* chore: regenerate docs skill after audit log response models
* fix(mcp): handle Claude Code GET probe and make stateless_http configurable (#751)
Claude Code v2.1.84+ sends a GET to /mcp/ before POST initialize,
which fails with 405 (stateless) or 400 (stateful). Intercept
sessionless GET requests in MCPMiddleware and return 200 OK so the
client proceeds to POST initialize.
Also make stateless_http configurable via HINDSIGHT_API_MCP_STATELESS
(default: false/stateful) instead of hardcoding true.
Closes#751
* docs: add HINDSIGHT_API_MCP_STATELESS to configuration reference
* Convert codex tool_choice test to pytest style
Follow-up to #734: replace unittest.TestCase + manual sys.path
manipulation with idiomatic pytest + @pytest.mark.asyncio,
matching the rest of the test suite.
* Fix test_hierarchical_fields_categorization for new configurable fields
Update expected count from 20 to 21 and add assertions for fields
added by recent PRs: retain_default_strategy, retain_strategies,
max_observations_per_scope, reflect_source_facts_max_tokens,
llm_gemini_safety_settings, mcp_enabled_tools.
* Add LlamaIndex doc to v0.4 versioned docs and sidebars
The LlamaIndex integration doc was added to docs/ (next version) in
#672 but not to versioned_docs/version-0.4/, causing a broken link
on the /integrations page which resolves to the latest version.
* Regenerate docs skill references
Run generate-docs-skill.sh to pick up new integration pages
(codex, llamaindex) and updated configuration docs.
* Add Codex integration doc to v0.4 versioned docs and sidebar
Same issue as LlamaIndex: doc was added to docs/ (next) but not
versioned_docs/version-0.4/, causing broken link on /integrations.
create_bank_hnsw_indexes() hardcoded USING hnsw regardless of the configured
vector extension, causing "column cannot have more than 2000 dimensions for
hnsw index" when using pgvectorscale or vchord with high-dimensional embeddings.
Now reads get_config().vector_extension and uses the appropriate index type:
- pgvector → USING hnsw
- pgvectorscale → USING diskann
- vchord → USING vchordrq
Closes#738
Verbose mode was the only extraction mode that skipped injecting the
retain_mission FOCUS section into its prompt template. Users who set a
retain_mission got no filtering when using verbose mode.
* fix(codex): cleanup dead code and add to release lifecycle
- Remove orphaned reflect() method from client.py (leftover from dropped auto-mode)
- Remove dead retainToolCalls config default (never wired through)
- Add codex to release-integration.sh valid integrations
- Add settings.json version fallback to release script
- Add codex CI test job in test.yml
- Add codex to integrations.json registry
* docs(codex): add changelog page and link from integration docs
* feat(codex): add hosted installer script (get-codex)
Add self-contained installer at hindsight.vectorize.io/get-codex that
downloads scripts from GitHub, configures hooks, and supports local/cloud
mode selection — no git clone required.
Update docs and README to use the one-liner install:
curl -fsSL https://hindsight.vectorize.io/get-codex | bash
* chore(codex): remove install.sh in favor of hosted get-codex
* fix(docs): use /next/ prefix for codex changelog link
* fix(docs): use GitHub link for codex changelog back-link
* feat(codex): add Hindsight memory integration for OpenAI Codex CLI
Hooks-based integration that gives Codex CLI long-term memory via Hindsight.
Three hooks keep memory in sync: SessionStart (daemon pre-warm), UserPromptSubmit
(recall + context injection), Stop (retain conversation to memory).
Key differences from the Claude Code integration:
- Codex transcript format: JSONL with {msg: {type, message}} (user_message/agent_message)
- No CODEX_PLUGIN_ROOT env var — install.sh writes hooks.json with absolute paths
- State stored in ~/.hindsight/codex/state/ (not CLAUDE_PLUGIN_DATA)
- No async: true in hooks (not supported by Codex)
- No SessionEnd event
- hooks.json written to ~/.codex/hooks.json with codex_hooks = true in config.toml
* fix(codex): fix transcript parser for actual Codex disk format
Codex stores sessions as rollout-*.jsonl with response_item entries:
User: {type:response_item, payload:{type:message, role:user, content:[{type:input_text, text:...}]}}
Assistant: {type:response_item, payload:{type:message, role:assistant, phase:final_answer, content:[{type:output_text, text:...}]}}
Previous parser expected an undocumented {msg:{type:user_message}} format from the Rust protocol spec
that does not match the actual on-disk storage format.
* feat(codex): add reflect mode to UserPromptSubmit hook
Add recallMode config option (default: 'recall') that switches the
UserPromptSubmit hook between:
- 'recall': existing behavior, fast raw facts list
- 'reflect': agentic synthesis loop, returns coherent prose answer
Also adds reflect() method to HindsightClient and HINDSIGHT_RECALL_MODE
env var override. Reflect uses a 25s timeout (vs 10s for recall).
* feat(codex): auto mode for recall/reflect selection
Add recallMode: 'auto' (new default) that picks the operation per-query:
- Synthesis patterns (what do you know, what's my, summarize, etc.) → reflect
- All other prompts → recall (fast, raw facts, better for code tasks)
* feat(codex): add automated test suite and finalize recall-only mode
* docs(codex): add docs page and sidebar entry for Codex CLI integration