This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
+3 more
Affected surfaces
Summary
AI summaryUpdates Behavior changes, New CLI commands, and New seeded entity types across a mixed release.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Feature | Medium |
Schema-level and per-entity agent instructions added for behavioral guidance. Schema-level and per-entity agent instructions added for behavioral guidance. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
Multi-harness preflight CLI replaces multi-prompt onboarding flow. Multi-harness preflight CLI replaces multi-prompt onboarding flow. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
Bulk harness-transcript import from ~/.claude/, ~/.codex/, and ~/.cursor/ added. Bulk harness-transcript import from ~/.claude/, ~/.codex/, and ~/.cursor/ added. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
MCP integration guides for Continue, Windsurf, VS Code, and Letta included. MCP integration guides for Continue, Windsurf, VS Code, and Letta included. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
Bidirectional column-encryption migration command for self‑hosted deployments added. Bidirectional column-encryption migration command for self‑hosted deployments added. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
Plan-entity refactor replaces feature units with first‑class plan entities and neotoma-plans mirror profile. Plan-entity refactor replaces feature units with first‑class plan entities and neotoma-plans mirror profile. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
Server-rendered /docs index over repo docs, fail‑closed visibility added. Server-rendered /docs index over repo docs, fail‑closed visibility added. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Feature | Medium |
Selective Claude PR review on substantial PRs implemented. Selective Claude PR review on substantial PRs implemented. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Timeline pagination now deterministic with secondary id ASC sort key. Timeline pagination now deterministic with secondary id ASC sort key. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Self‑hosted auth for key‑file‑only deployments and Cloudflare Tunnel topology fixed (#79). Self‑hosted auth for key‑file‑only deployments and Cloudflare Tunnel topology fixed (#79). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
NEOTOMA_TRUSTED_PROXY_IPS discovery logging improved; untrusted XFF IPs redacted. NEOTOMA_TRUSTED_PROXY_IPS discovery logging improved; untrusted XFF IPs redacted. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
external_link entity type with gist metadata fields fixed (#72, #75, #77, #84). external_link entity type with gist metadata fields fixed (#72, #75, #77, #84). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
remote_submission_error set to null on early return path. remote_submission_error set to null on early return path. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
@neotoma/client alias resolution fixed in vitest and opencode-plugin (#107, #109, #132). @neotoma/client alias resolution fixed in vitest and opencode-plugin (#107, #109, #132). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
CI checkout step added to claude-code-action workflow; id-token handling corrected. CI checkout step added to claude-code-action workflow; id-token handling corrected. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Security classifier JSON output now strips npm script header line. Security classifier JSON output now strips npm script header line. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Site wordmark included in site_pages build output (#122). Site wordmark included in site_pages build output (#122). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Issue access reset-issue-policy correctly writes default to disk (#40, #89). Issue access reset-issue-policy correctly writes default to disk (#40, #89). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Schema-projection lag for recurring events fixed (#37, #115). Schema-projection lag for recurring events fixed (#37, #115). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Multiple-active-schema rows causing raw_fragments misrouting repaired (#142). Multiple-active-schema rows causing raw_fragments misrouting repaired (#142). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
db migrate-encryption rowid-aliasing latent bug fixed. db migrate-encryption rowid-aliasing latent bug fixed. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
store schema canonical_name_fields and combined unknown-fields / idempotency-mismatch fix (c8f497198). store schema canonical_name_fields and combined unknown-fields / idempotency-mismatch fix (c8f497198). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
store_structured / store_unstructured alias dispatch in MCP executeTool path. store_structured / store_unstructured alias dispatch in MCP executeTool path. Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
store ranking and AUTH_REQUIRED hint plus auto‑populated reporter_app_version (#181, #182, #183, #191, #206). store ranking and AUTH_REQUIRED hint plus auto‑populated reporter_app_version (#181, #182, #183, #191, #206). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
conversation schema and session UUID bridge fixed (#138, #145, #256). conversation schema and session UUID bridge fixed (#138, #145, #256). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
product_feedback feedback_source discriminator and identity validation added (#136, #137). product_feedback feedback_source discriminator and identity validation added (#136, #137). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
workout_session schema with merge_array exercises implemented (#209). workout_session schema with merge_array exercises implemented (#209). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
Plan entity retrieval routing fixed (#228). Plan entity retrieval routing fixed (#228). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
SQLite lock retry with exponential backoff added (#173). SQLite lock retry with exponential backoff added (#173). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
| Bugfix | Medium |
CLI bugs: getProjectRoot resolution, doctor data_dir_source, local transport probe, upload --local data dir fixed (#168, #170, #171, #172). CLI bugs: getProjectRoot resolution, doctor data_dir_source, local transport probe, upload --local data dir fixed (#168, #170, #171, #172). Source: granite4.1:8b-q6_K@2026-05-19 Confidence: high |
— |
Full changelog
v0.13.0 Release Supplement
Summary
v0.13.0 is a substantial feature release covering everything since v0.12.1. Headline additions:
- Schema-level and per-entity agent instructions — entity types and individual entities can carry behavioral guidance that agents must apply when the entity is retrieved.
- Multi-harness preflight CLI — replaces the multi-prompt onboarding flow.
- Bulk harness-transcript import from
~/.claude/,~/.codex/, and~/.cursor/. - MCP integration guides for Continue, Windsurf, VS Code, and Letta.
- Bidirectional column-encryption migration command for self-hosted deployments.
- Plan-entity refactor — replaces feature units with first-class
planentities and aneotoma-plansmirror profile. - Server-rendered
/docsindex over repo docs, with fail-closed visibility. - Prettier baseline + CI format gate.
- Selective Claude PR review on substantial PRs.
- Corrective fixes to schema discovery, idempotency, intra-batch relationships, raw_fragments routing, and timeline determinism.
GitHub Releases now stage as draft and publish only after the sandbox deployment is verified. The release flow opens an RC branch + PR for public review before execute.
What changed for npm package users
New CLI commands
neotoma preflight [--tool <harness>] [--apply] [--scope project|user|both] [--dry-run]— prints a copy-paste allowlist block for the specified harness or writes it directly with--apply. Allowlist writes are supported forclaude-code,cursor, andcodex; for MCP-only harnesses (claude-desktop,openclaw,windsurf,continue,vscode) the command prints a redirect toneotoma setup. Forclaude-code,--scopeselects project (.claude/settings.local.json), user (~/.claude/settings.json), or both. Replaces the multi-prompt manual setup that previously plagued the onboarding flow.neotoma db migrate-encryption <encrypt|decrypt>— bidirectional bulk column encryption migration that operates directly on the SQLite file (no running server). Migratesobservations.fields,entity_snapshots.snapshot/provenance,relationship_snapshots.snapshot/provenance,raw_fragments.fragment_value/fragment_envelope, andschema_recommendations.fields_*/converters_to_add. Uses the same key configuration as the runtime (NEOTOMA_KEY_FILE_PATHorNEOTOMA_MNEMONIC+ optionalNEOTOMA_MNEMONIC_PASSPHRASE). Covered bytests/cli/db_migrate_encryption.test.ts(encrypt→decrypt identity, idempotency, dry-run non-mutation, NULL preservation, missing-table skip, wrong-key per-row failure, INTEGER PRIMARY KEY rowid-aliasing fix).neotoma db repair-schema-lag [--dry-run] [--types <entity_types>] [--rollback <run_id>]— audit and repairraw_fragmentsrows that were misrouted due to the schema-projection-lag bug (#142). Rows whosefragment_keynow matches a declared field in the active schema are promoted to observations and snapshots recomputed. Every inserted observation carries a_migration_run_idfield for rollback. Covered bytests/cli/db_repair_schema_lag.test.ts.neotoma db migrate-env-split— repairs npm-installed deployments that had previously written user data to a dev database. Subsequent installs now default to a production DB; this command moves existing data into the production location (#172, #244).neotoma schemas repair-plural-types— coalesces accidentally-plural entity types (e.g.posts→post) back to the canonical singular form, declaring the plural as an alias on the canonical schema (#162).neotoma onboarding import-transcriptsandneotoma init --import-transcripts— bulk-import all detectable harness transcripts in one step during onboarding (#143).neotoma reporter setup— guided setup for the issue reporter flow (auth, scope, default labels), supersedes the multi-step manual procedure (#199).
New CLI flags on existing commands
neotoma discover --harness-transcripts— also detects Claude Code (~/.claude/projects/*/conv-*.jsonl), Codex (~/.codex/archived_sessions/*.jsonl), and Cursor (~/.cursor/chats/**/store.db, plusstate.vscdb) transcript locations. Prints a structured summary with file counts, sample titles, date ranges, and SQLite requirement flags.neotoma ingest-transcript [path] --harness <claude-code|codex|cursor>—pathis now optional. When--harnessis given andpathis omitted, bulk-imports all transcripts from the corresponding well-known location.neotoma cursor-hooks --global— installs cursor hooks into~/.cursor/hooks.jsoninstead of the project-local.cursor/hooks.json(#144).neotoma store --turn-key <key>— stable per-turn idempotency key surface for replay-safe stores; used internally by the test suite and supported for external callers.neotoma sync-issues --push— new push leg that mirrors local public Neotoma issues to GitHub with PII redaction applied at the boundary.
Behavior changes in existing commands
neotoma store/retrieve_entities— entity responses now include two new nullable string fields:schema_instructions— markdown sourced fromSchemaDefinition.agent_instructionsfor the entity's registered schema.entity_instructions— markdown sourced from the entity's own snapshotagent_instructionsfield.
Agents MUST treat these as behavioral context for the entity type and apply them to the current turn.
neotoma store— unknown-field surfacing improved: the response now includes a concrete list of unknown field names (not just a count) when fields are dropped toraw_fragments, and emits a structured recovery hint pointing the caller at the right corrective action (#185, #187). A pre-resolution pass prevents partial batch writes — if any entity in a batch fails to resolve, none are written (#203). Intra-batch relationships are honored: a relationship targeting another entity created in the samestorecall now resolves correctly (#203, #221).neotoma store— schema/type discovery is required before the store completes; callers receive a clear error when targeting an unregistered entity type instead of silently routing all fields toraw_fragments(#196, #208). When the target type has no registered schema, the response surfaces the no-schema state explicitly so callers can register a schema and retry (#164).neotoma store— idempotency key reuse with a different payload is now detected via content-hash comparison and returnsERR_IDEMPOTENCY_MISMATCHinstead of silently overwriting (#186).neotoma storealiases — the MCP dispatcher now recognisesstore_structuredandstore_unstructuredaliases for the unifiedstoretool.neotoma storeranking — store-tool ranking improved so agents surface the right entry point when multiple variants match (#181, #182, #183, #191, #206).neotoma retrieve/list_timeline_events—list_timeline_eventsreturns an empty result for an unknownevent_typeinstead of erroring (#207).neotoma sourcesaccess mutation commands now fail fast when--base-urlor--api-onlyare present (these commands are local-only).neotoma issue add-messagetreats partial success (GitHub write succeeded, remote Neotoma append failed) as success, returning a non-nullremote_submission_errorso callers can react without an end-to-end failure (#43, #90).neotoma cli access reset-issue-policycorrectly writes the default policy to disk (#40, #89).neotoma doctor— reports the source of the resolveddata_dirso users can tell when the path came from an env var, default, or explicit flag (#170).neotoma upload—--localcorrectly uses the local data dir for source persistence (#168).neotoma submit-issue/add-issue-message—reporter_app_versionis auto-populated when not supplied;AUTH_REQUIREDerrors now surface a structuredhintdirecting the caller at the right next step (#181, #182).neotoma plans— new top-level surface backed byplanentities (see Plan refactor below).
New seeded entity types
plan— first-class entity for engineering and design plans, replacing the previous filesystem-only feature units. Plans are mirrored back toplans/(wasdocs/plans/) via the newneotoma-plansmirror profile.gist— GitHub Gists and similar code/text snippets shared via URL. Identity uses gist URL; preserves description casing; last-write merge for description (#72, #75, #77, #84).neotoma_repair— records a repair or remediation action taken within Neotoma. Identity is composed of action + timestamp + actor.external_link— generic external URL entity with gist-style metadata fields (title, description, source).conversation— promoted from inferred to bootstrap-registered schema;session_uuidfield added as a bridge to coalesce slug-style conversation IDs with harness-issued UUIDs (#138, #145, #256).workout_session— new schema with anexercisesfield usingmerge_arraysemantics (#209).product_feedback— adds afeedback_sourcediscriminator and tightened identity validation (#136, #137).
Plan refactor
Plans are now first-class Neotoma entities, not filesystem documents. Highlights:
- Plans live as
planentities with structured fields, retrieval routing, and graph edges to objectives, gates, and feedback. - The new
neotoma-plansmirror profile snapshotsplanentities into the repo with canonical-name filenames and YAML frontmatter for harness compatibility. - Plan content moved out of
.cursor/plans/anddocs/plans/flat files into Neotoma; the mirror writes them back toplans/for harness visibility (b1d163696). - Selective mirror profiles support snapshot field tokens, slug truncation, and a remote API client for profile-based hydration (
8d39d1000,7a441614f). - Plan-entity retrieval routing fixed so
planqueries return plan entities and not the conversation that referenced them (#228, #233). - A new
renderProfileEntityhelper emits harness-compatible YAML frontmatter for profile rendering (#241).
API surface & contracts
- New nullable response fields on entity objects in
openapi.yaml:schema_instructions: string | null— fromSchemaDefinition.agent_instructions.entity_instructions: string | null— from snapshotagent_instructions.
submit_issueandadd_issue_messageaccept a new optionalentity_ids_to_link: string[]; the server createsREFERS_TOrelationships from the issue (or message) to the referenced entities in the same operation, so callers no longer need a follow-up relationship write (#131, #146, #147).add_issue_messageresult schema addsremote_submission_error: string | null. Non-null when remote Neotoma append failed after local and/or GitHub side effects were already recorded.- HTTP
keepAliveTimeoutextended to prevent MCP session drops behind reverse proxies (#148). POST /create_relationshiprequest schema declared (additionalProperties: false, three required fields:relationship_type,source_entity_id,target_entity_id; three optional:source_id,metadata,user_id). The handler has always validated these via Zod; the OpenAPI spec is now aligned. See Breaking changes section.- MCP
create_relationshipandlist_entity_typestool schemas declared explicitly so MCP clients can introspect required and optional parameters (#159, #161). Previously these surfaced as schema-less or untyped tools to some clients. storeresponse shape extensions —unknown_fields(array of names, not just a count),no_schema_for_entity_typeflag, content-hash mismatch error path with structured hint.- New unauthenticated route
GET /docs/GET /docs/*— serves repodocs/**.mdas a browsable read-only documentation tree (fail-closed visibility, see Security hardening). - No endpoints removed. No type narrowings on existing previously-declared fields other than the create_relationship body alignment.
Behavior changes
- Timeline pagination is now deterministic.
GET /timelinepreviously sorted only byevent_timestamp(orcreated_atwhen explicitly requested). When many events shared the same timestamp, page boundaries were unstable so events could repeat across pages or be skipped. A secondaryid ASCsort key now applies. Aligns withdocs/architecture/determinism.md. - Schema-level agent instructions.
SchemaDefinition.agent_instructionsis now a validated optional field. When set, it is returned alongside every entity of that type so agents in the loop see the relevant behavioral context. - Per-entity agent instructions. An entity's snapshot may carry its own
agent_instructionsfield which extends or overrides the schema-level instructions for that specific entity. - Schema auto-enhancement gates relaxed for trusted sources. Thresholds drop to
ceil(base * 0.5)for user-scoped schemas when the observation source isllm_summary,import, orsync. Does not apply to global schemas (#98, #102). - Interpretation orders fragment writes after entity resolution. Buffer raw_fragment writes until after entity resolution completes so they land against the correct resolved entity ID (#163).
- SQLite lock retry. Read and write operations now retry with exponential backoff on
SQLITE_BUSY/SQLITE_LOCKEDinstead of failing immediately, which removes a class of flaky errors under concurrent agent load (#173). - Recurring event field projection. Recurring-event fields now project correctly into snapshots (#37, #115).
- Null correction clears date fields from snapshot. A correction that writes
nullto a date field now removes it from the snapshot instead of leaving the previous value (#41, #104). - Source existence validated before creating an interpretation.
interpretnow returns a clearSource not found: <id>error instead of orphan rows. - Canonical mirror commits work in unconfigured environments. The git-backed canonical mirror provides a fallback
user.name/user.emailso commits succeed in CI and other environments without a global git identity. - Untrusted
X-Forwarded-ForIPs are redacted in log lines.isLocalRequestlog output no longer leaks raw client IPs from spoofed headers (PII hardening). - Neotoma entity IDs carved out of phone-number PII redaction. Entity IDs of the form
ent_*are no longer matched as phone numbers (#130, #134). - Hook bridge: session UUID coalescing. The hook bridge now coalesces slug-style
conversation_ids with harness-issued session UUIDs against the bootstrap-registeredconversationschema, eliminating duplicate conversation entities per session (#145, #153, #256). - Automated-sender extraction. Agent instructions now require organization and contact extraction for automated email senders (no-reply, alerts, etc.), bringing them into the entity graph instead of dropping them (#198).
- npm-installed default database environment. New npm installs default to a production database (was: dev). Existing dev installs are migrated via
neotoma db migrate-env-split(#172).
Docs site & CI / tooling
- Server-rendered
/docsindex over repodocs/**.mdfiles, with fail-closed visibility (docs/private/never served, unmappeddocs/*/paths default to internal). XSS-safe rendering,Cache-Control: public, max-age=60, in-process cache keyed by manifest and tree mtime. New visibility model documented insrc/services/docs/doc_frontmatter.ts. - MCP integration guides added for Continue, Windsurf, VS Code, and Letta. Each guide ships with a frontend subpage and a docs site MDX page.
- Mobile MCP setup guide added; compact MCP instructions mode documented (#93, #105).
- Pre-release checklist and tunnel auth audit matrix added under
docs/developer/. - Cloud-fronted caller auth section added to the tunnel guide with an advisory operational note (covers Cloudflare Tunnel topology).
install.mdupdated — Step 2.1 callsneotoma preflight --tool <tool> --apply; harness transcript detection block added.docs/developer/cli_reference.mdupdated with the new commands and flags listed above.SECURITY.md— Supported Versions table updated (0.13.xYes,0.12.xYes,< 0.12No).- CI: Prettier format gate enforced in pre-commit and the CI baseline lane (#166, #167). Baseline Prettier pass applied across
src/. - CI: Claude PR review GitHub Action triggers on every push to open non-draft PRs (#111, #119); pre-review reading list wired in. Reviewer scoped, throttled, de-looped (skip synchronize re-reviews for castor-agent PRs; cap at 15 turns; 60-minute timeout; diff-size gate; switched to Max plan OAuth with concurrency guard).
packages/**paths and substantial-diff gate added (#243). - CI: selective
@claudereview on substantial PRs via/process_prsinstead of every push (#237 + follow-ups). - CI: baseline job isolates integration test DB state to eliminate shared-state flakiness (#126).
- CI:
@neotoma/clientalias resolution fixed in vitest and the opencode-plugin (#107, #109, #132). - CI: security classifier JSON output no longer includes the npm script header line.
- Site:
neotoma-wordmark.svgships with site_pages build output (#122). - Site: status banners on partly-shipped proposals; stale artifacts archived (
de598863e,15ee7c770). - Release skill: GitHub Releases stage as draft and publish only after sandbox deploy verification — eliminates the window where a release appears as "latest" before the deployed surface matches. New RC branch + PR step opens
release/vX.Y.Z→mainand stops for public review before execute (this skill). fly.toml— Fly.io app renamed fromneotomatoneotoma-sandbox; data volume mount added so the SQLite file persists across deploys (#117).- launchd: prod-server hot-reload via
dev:server:prod— switches the production launchd job to a source build with hot reload. - Standards scaffolding — PR template, CODEOWNERS, format scripts, severity-mapping docs (#165).
/auditskill, FU spec, and manifest added for Neotoma graph-health audits./design_issuesskill for working needs-design issues to resolution (#237)./process_prsskill for triage, security check, Opus review request on substantial PRs, merge, and release detection./publish_planskill to convert a plan entity into a GitHub Discussion post.
Internal changes
- Plan-entity refactor.
.cursor/plans/andplans/flat files migrated intoplanentities; the newneotoma-plansmirror profile writes them back toplans/for harness visibility. Touches schema definitions, store routing, retrieval routing, and the mirror service. src/cli/preflight.ts(new) — standalone permission-file writer for the newpreflightcommand.src/cli/discovery.ts(new) — harness transcript detection (Claude Code JSONL, Codex JSONL, Cursor SQLitestore.db+state.vscdb).src/cli/commands/db.ts(expanded) — addsdb migrate-encryption,db repair-schema-lag, anddb migrate-env-split.src/services/schema_lag_repair.ts(new) —auditEntityType,repairEntityType,auditAll,repairAll,rollbackRun. Deterministic observation IDs (SHA-256 ofentity_id:run_id).src/services/schema_registry.ts— validates and persistsSchemaDefinition.agent_instructions; explicitly deactivates all prior active versions before returning a newly registered row (the #142 fix); plural-type repair backend.src/services/schema_definitions.ts— addsgist,neotoma_repair,external_link,plan,workout_session; promotesconversationto bootstrap; extendsproduct_feedbackwithfeedback_source.src/services/schema_recommendation.ts—trusted_source_relaxationconfig plusTRUSTED_OBSERVATION_SOURCES = {llm_summary, import, sync}allowlist.src/services/docs/doc_frontmatter.ts+src/services/docs/docs_index.ts(new) — fail-closed/docsvisibility model and server-rendered index.src/cli/transcript_parser.ts— major expansion. Addsconversation_idextraction; broadened harness parsing; Cursorstate.vscdband per-workspacestore.dbSQLite parsing covering hex-encoded and raw-buffer blobs, structured content blocks, malformed JSON skip, missing-table fallback, corrupt-file fallback.src/server.ts— wiresqueueSchemaLagRepairon server startup;entity_ids_to_linkplumbing onsubmit_issueandadd_issue_message; MCP instruction body refreshed; skips SIGINT/SIGPIPE handlers in test environment; HTTPkeepAliveTimeoutextension.src/repositories/sqlite/sqlite_client.ts— exponential-backoff retry onSQLITE_BUSY/SQLITE_LOCKED(#173); minor extension to support repair service queries.src/services/auto_enhancement_processor.ts— schema-lag repair integration; repair-candidate fragments bypassed from auto-enhancement queue.src/services/mirror/*— selective profiles, canonical-name filenames, snapshot field tokens, slug truncation, remote API client,renderProfileEntityhelper,neotoma-plansprofile.- MCP instruction file (
docs/developer/mcp/instructions.md) — narrative refresh covering schema-instruction handling, retrieval-first behavior, image-only compliance, global-conservative reducer policy (#97, #99, #93, #95), PII stripping checklist forsubmit_issue/add_issue_message(#139), schema/type discovery first (#196, #208), per-record extraction, schema-first store (#160, #174, #175, #176), automated-sender organization/contact extraction (#198), auto-file consent (#250). Misnomer renamed; openclaw drift fixed; harness table added (98d0907da). scripts/backfill_harness_transcripts.ts— loads.env.production, surfaces child-process stderr, accepts--base-urland explicit env injection.scripts/audit_raw_fragments_schema_lag.ts— expanded from stub to full audit script.scripts/check_migration_run.ts(new) — operational helper for verifying a migration run completed and stored correctly.- Skill directories —
.claude/skills/and.cursor/skills/renamed kebab-case → snake_case. New skills:process_prs,publish_plan,shadcn,audit,design_issues. - Frontend — Castor agent avatar and mascot concept renders added under
frontend/src/assets/images/mascots/. SEO metadata expanded. - Gmail proactive check Cursor rule — directs agents to check Gmail when task context implies email may be relevant.
packages/cursor-hooks— vendoredneotoma-clientno longer ships a hardcoded dev-local token in the published artifact.
Fixes
- Timeline pagination non-determinism (data-layer, high impact): adding
id ASCas a secondary sort key. Regression test intests/cli/cli_timeline_commands.test.ts. - Self-hosted auth for key-file-only deployments and Cloudflare Tunnel topology (#79) — token resolution works when only
NEOTOMA_KEY_FILE_PATHis set; tunnel-fronted topology produces correct auth response. NEOTOMA_TRUSTED_PROXY_IPSdiscovery logging —isLocalRequestlogs untrusted XFF IPs (redacted) so operators can identify the correct CIDR to allowlist.isLocalRequestlog line PII — untrusted XFF IPs in the rejection log are redacted; setNEOTOMA_DEBUG_TUNNEL=1to see full IPs.external_linkentity type with gist metadata fields, plus identity/canonical-name fixes forgistandneotoma_repair(#72, #75, #77, #84).remote_submission_error: nullon theAddMessageResultearly-return path.@neotoma/clientalias resolution in vitest and opencode-plugin (#107, #109, #132).- CI checkout step in
claude-code-actionworkflow;id-token:writeandgithub_tokenadded;CLAUDE_CODE_OAUTH_TOKENpassed correctly (1eb2957bd). - Security classifier JSON output strips the npm script header line.
- Site wordmark included in
site_pagesbuild output (#122). - Issue access reset-issue-policy correctly writes default to disk (#40, #89).
- Schema-projection lag for recurring events (#37, #115) — fields now project into the snapshot.
- Multiple-active-schema rows causing raw_fragments misrouting (#142) — when
registerSchemawas called withactivate: true, prior active rows for the sameentity_type+ scope were not deactivated.loadGlobalSchema/loadUserSpecificSchemause.single(), so a second active row caused the call to error; new observations were silently routed toraw_fragments. Fixed insrc/services/schema_registry.ts. Regression test:tests/unit/schema_projection_lag.test.ts. Deployments that ingested data while the bug was active can recover misrouted rows usingneotoma db repair-schema-lag. db migrate-encryptionrowid-aliasing latent bug — SQLite rewritesrowidto the declared primary-key column name when a table hasINTEGER PRIMARY KEY. Fixed by aliasingrowid AS _migration_rowid. Regression test intests/cli/db_migrate_encryption.test.ts.storeschema canonical_name_fields and combined unknown-fields / idempotency-mismatch fix (c8f497198) — see Behavior changes in existing commands for caller-facing detail (#164, #185, #186, #187, #203, #221).store_structured/store_unstructuredalias dispatch in the MCP executeTool path.storeranking and AUTH_REQUIRED hint plus auto-populatedreporter_app_version(#181, #182, #183, #191, #206).conversationschema and session UUID bridge (#138, #145, #256).product_feedbackfeedback_sourcediscriminator and identity validation (#136, #137).workout_sessionschema with merge_array exercises (#209).- Plan entity retrieval routing (#228).
- SQLite lock retry with exponential backoff (#173).
- CLI bugs:
getProjectRootresolution, doctordata_dir_source, local transport probe, upload--localdata dir (#168, #170, #171, #172). - Recurring duplicate
renderProfileEntitydeclaration (#241 follow-up). mcp_ironclaw_setup.mdfull-path reference restored in overview (70aa1c810).- PR review carryovers: addressed overlooked findings from PRs #224/#178, #233/#232/#151, #152/#222/#223, and #153 hook bridge hardening (
cc9fa5407,61919140b,69ca88230,f194cad25).
Tests and validation
- Full unit + integration test suite green on HEAD.
- G2 (
security:lint): 0 errors; warnings are pre-existing patterns. - G3 (
security:manifest:check+test:security:auth-matrix): manifest in sync; auth matrix passes. - G4 (
security:ai-review): seedocs/releases/in_progress/v0.13.0/security_review.md; verdictwith-caveats. - Test catalog regenerated; Prettier baseline applied repo-wide.
Test files added across this range include (non-exhaustive):
tests/cli/cli_access_commands.test.tstests/cli/cli_doctor_setup.test.tstests/cli/cli_onboarding_commands.test.tstests/cli/cli_timeline_commands.test.ts(tightened pagination test)tests/cli/discovery_harness.test.tstests/cli/transcript_parser.test.ts(with cursorstate.vscdbandstore.dbcoverage)tests/cli/db_migrate_encryption.test.ts(round-trip + INTEGER PRIMARY KEY case)tests/cli/db_repair_schema_lag.test.tstests/cli/cursor_hooks_global.test.tstests/cli/discover_to_parse_roundtrip.test.tstests/integration/issue_37_event_schema_projection.test.tstests/integration/mcp_store_canonical_name_unknown_fields.test.tstests/integration/store_builtin_identity_opt_out_schemas.test.tstests/integration/store_explicit_canonical_name.test.tstests/integration/store_external_link_schema.test.tstests/services/schema_recommendation.test.tstests/unit/observation_reducer_projection.test.tstests/unit/schema_agent_instructions.test.tstests/unit/schema_projection_lag.test.tstests/unit/keepalive_timeout.test.tstests/unit/store_alias_dispatch.test.tstests/unit/submit_issue_dx.test.tstests/unit/workout_session_schema.test.ts
Security hardening
npm run security:classify-diff -- --base v0.12.1 --head HEAD flagged sensitive=true. Concerns reviewed:
- openapi-security — response field additions (
schema_instructions,entity_instructions,entity_ids_to_link,remote_submission_error,unknown_fieldslist) on existing secured endpoints. No security blocks changed. No new authenticated endpoints removed. - auth-middleware —
src/actions.tsmodified for the timeline determinism fix only.isLocalRequest,forwardedForValues,LOCAL_DEV_USER_ID, andassertExplicitlyTrustedare unchanged from v0.12.1. - new unauthenticated route
/docs— added toprotected_routes_manifest.jsonruntime-only unauth allowlist with stated reason (serves public repo markdown). Fail-closed visibility model (docs/private/never served; unmapped paths default to internal; XSS-safe rendering; safe-scheme link rewriting). Reviewed via PR #178.
Review artifact: docs/releases/in_progress/v0.13.0/security_review.md.
Operational hardening landing in this release:
- Untrusted XFF IPs redacted in
isLocalRequestrejection logs (PII). NEOTOMA_TRUSTED_PROXY_IPSdiscovery messages documented for CGNAT / Warp / Cloudflare Tunnel scenarios.cursor-hooksplugin no longer ships a hardcoded dev-local token in the published artifact.- Cloud-fronted caller auth section added to the tunnel guide.
- Issue push leg redacts PII at the GitHub boundary before mirroring local issues out.
- Public
/docsroute defaults unknown subtrees tointernal(fail-closed) and rewrites unsafe link schemes.
No new security advisories opened for this release.
Breaking changes
POST /create_relationship— request body schema declared withadditionalProperties: false. The OpenAPI spec previously declared an open schema with no fields. The handler has always validatedrelationship_type,source_entity_id, andtarget_entity_idas required viaCreateRelationshipRequestSchema(Zod) and rejected unknown fields, so behavior is unchanged. The spec now matches the handler. Migration: ensure callers send only the declared fields (relationship_type,source_entity_id,target_entity_id, optionalsource_id,metadata,user_id). Any caller already compliant with the Zod validation is unaffected.MCP create_relationshipandlist_entity_typestool schemas now declared. MCP clients that previously sent ad-hoc fields through these tools will see explicit validation errors against the declared schema. Aligns the MCP surface with the HTTP surface (#159, #161).storeidempotency-key reuse with different payload returnsERR_IDEMPOTENCY_MISMATCH. Previously, reuse silently overwrote. Callers relying on the silent-overwrite behavior must either use a new idempotency_key per distinct payload or use the explicitcorrectflow (#186).storepartial-batch writes are no longer possible. A pre-resolution pass aborts the whole batch if any entity fails to resolve. Callers that relied on partial writes must split their input (#203).storeschema/type discovery required before completion. Targeting an unregistered entity type now returns a structured error instead of silently routing all fields toraw_fragments. Callers must register the schema (or accept theno_schema_for_entity_typeflag and re-store after registration) (#196, #208).- npm-installed default database environment switched to production. New npm installs default to a production DB. Existing dev installs continue to work and can be migrated explicitly via
neotoma db migrate-env-split(#172). - Plans relocated from
.cursor/plans/anddocs/plans/toplans/(mirrored from Neotoma). Tooling that referenced the previous paths must update; the canonical source is now theplanentity, and the on-disk mirror isplans/. - Skill directories renamed from kebab-case to snake_case under
.claude/skills/and.cursor/skills/. Symlinks may need refreshing vianpm run setup:cursor.
MCP agent instructions changes
docs/developer/mcp/instructions.md received significant additions in this release. The file is the behavioral contract the Neotoma MCP server sends to clients at runtime, so these changes take effect without any code changes on the agent side — as soon as the server is updated, connected agents receive the updated instructions.
New mandatory rules
-
Image-only message compliance. When the user message contains only an image or screenshot (no text), all five turn-lifecycle steps still MUST execute. Agents must store a
conversation_messagedescribing the image and extract any entities visible in it (tasks, events, contacts, transactions). (#93, #95) -
Short-pass compliance. Doc-only edits,
neotoma cli config, single-file lint tweaks, and other minimal turns are explicitly NOT exempt from steps 1–5. Rationalizing a store skip as "analysis-only", "in-session bookkeeping", or "just an evaluation" is FORBIDDEN. (#93) -
PII stripping checklist before issue filing. A mandatory six-point checklist must be completed before every
submit_issueoradd_issue_messagecall: strip names/emails/phones, replace private identifiers withent_*IDs or generic labels, redact credentials and verbatim sensitive data, and re-read the body before calling. (#139) -
Issue entity linking after filing. Immediately after
submit_issuereturns, agents MUST callcreate_relationshipswith REFERS_TO edges to every Neotoma entity that motivated or is referenced by the issue. Likewise foradd_issue_message. Previously these edges were optional. (#131, #135) -
Schema-level and per-entity agent instructions. When
retrieve_entitiesorretrieve_entity_snapshotreturns aschema_instructionsorentity_instructionsfield, agents MUST treat those strings as behavioral context and apply them to the current turn. FORBIDDEN: ignoring these fields when present. (#129, #146) -
Schema-first store for unfamiliar types. Before the first
storefor an entity_type the agent has not used this session and that is not in the common-types short list, calllist_entity_typeswith a keyword to discover whether a registered schema exists. FORBIDDEN: storing with an unfamiliar entity_type via intuited fields without a schema check. (#160, #174, #175, #176, #196, #208) -
Unknown-fields mandatory repair. If any entity in a store response has
unknown_fields_count > 0, agents must immediately re-store orcorrectthose entities using declared field names before proceeding to the closing assistant store. (#185, #187) -
Automated sender extraction. For every sender of an external-source record (email, notification, invoice), agents must create or match a
contactentity for the sender address AND anorganization/companyentity for the underlying service, even for automated senders (no-reply, alerts, invoicing addresses). FORBIDDEN: extracting only the transactional payload without persisting the organization and sender contact. (#198) -
Session UUID bridge (Claude Code). In Claude Code contexts, agents must call
get_session_identityonce per session and includesession_uuidon the slug-keyedconversationentity. This coalesces the hook-created UUID entity with the agent-created slug entity so hook-written timeline events correlate with MCP conversation data. FORBIDDEN: omittingsession_uuidwhenget_session_identityis available and returns a value. (#145, #153, #256) -
Proactive auto-file mandate. When
issues.reporting_modeisproactive, agents MUST callsubmit_issuefor every qualifying finding in the same turn with no user confirmation prompt. FORBIDDEN: pausing to ask "should I file this?" when proactive mode is set. (#250) -
Retrieval-first for common query types. When the user asks about tasks, schedule, contacts, notes, issues, events, finances, decisions, or commitments, agents MUST run a bounded Neotoma retrieval pass before answering or falling back to native integrations. (#97, #99)
-
Named entity-type routing. When the user asks about a named entity type ("newest plans", "my tasks", "open issues"), agents must call
retrieve_entitieswith the matchingentity_typedirectly. FORBIDDEN: searching conversation history as a substitute for a direct entity query. (#228) -
Artifact store triggers. When a concrete artifact is approved or finalized in conversation (plan, schema_design, decision_record, feature_spec, etc.), agents must store it in the same turn without waiting for an explicit save instruction. FORBIDDEN: ending a turn where an artifact was finalized without storing it.
-
TodoWriteis session-local. The host toolTodoWritedoes NOT satisfy the Neotoma store protocol. Persistent follow-up tasks must also be stored viaentity_type: "task"in Neotoma. FORBIDDEN: usingTodoWritealone to record tasks that should persist beyond the current session.
Clarifications and fixes
-
Fallback turn_key scoping. Bare
chat:<turn>turn_keys are now explicitly FORBIDDEN — they reuse across sessions and cause cross-session entity merges. The correct fallback is a session-epoch-scoped key (chat-<session_epoch_ms>:<turn>). (#127) -
Conversation entity maintenance. When a conversation pivots materially in scope, agents must update
titleandscope_summaryon the existing conversation entity. FORBIDDEN: minting a new conversation entity or newconversation_idto represent the new scope. -
Tool deregistration recovery. When a tool call fails with "tool 'Neotoma:X' is not registered", agents must call
tool_searchto reload it and retry. This is a client-side cache eviction, not a server-side removal. -
parse_fileis not file retention.parse_fileis a read-only inspection tool that writes nothing to Neotoma. Retention requires a subsequentstorecall withfile_pathorfile_content+mime_type. FORBIDDEN: treating a successfulparse_filecall as sufficient persistence. -
Transport precedence. When both
neotoma(prod) andneotoma-devMCP servers are connected, default toneotomafor all retrieval and store operations. Dev and prod are separate SQLite databases — data written to one is not visible in the other. -
Harness table added. A new table of supported harnesses (Claude Code, Cursor, Codex, Continue, Windsurf, VS Code, Claude Desktop, Letta) with their configuration paths was added to the onboarding section. (
98d0907da)
Upgrading from v0.12.x — repair and migration guide
Most upgrades are drop-in. The items below are opt-in repair and migration commands for deployments that were running during the affected window and may have accumulated data-quality issues from bugs fixed in this release. None are required if you are installing v0.13.0 fresh.
1. Repair misrouted raw_fragments rows (schema-projection lag) — recommended for all existing deployments
Bug: When registerSchema was called with activate: true, prior active schema rows for the same entity type were not deactivated. loadGlobalSchema uses .single(), so a second active row caused an error and new observations were silently routed to raw_fragments instead of the entity snapshot. Any entity type that was re-registered (e.g. during onboarding or version upgrades) was affected. (#142)
Impact: Entity snapshots for affected types are incomplete — fields that should be first-class observations are in raw_fragments and invisible to retrieval and the reducer.
Fix (automatic on server start): queueSchemaLagRepair runs on startup in v0.13.0 and queues a background audit. To verify the repair or run it on large databases, run manually:
neotoma db repair-schema-lag
Options: --dry-run audits without writing; --types <types> limits to specific entity types; --rollback <run_id> reverses a prior run. The repair is fully reversible.
2. Migrate npm installs to production database — required for npm-installed deployments that pre-date this release
Bug: Prior npm installs defaulted to the dev database (neotoma.db). v0.13.0 defaults to the production database (neotoma.prod.db). Existing deployments will appear empty after upgrading because the server now opens a different file. (#172)
Fix:
neotoma db migrate-env-split
Run once immediately after upgrading. Self-hosted installs that set NEOTOMA_DATA_DIR explicitly are unaffected.
3. Repair accidentally-plural entity types — if applicable
Bug: The naming convention requires singular entity_type names. Deployments with plural types (e.g. posts, transactions) have fragmented entity graphs — queries for the singular canonical form will miss records stored under the plural variant. (#162)
Check first with neotoma schemas list. If any types are plural, run:
neotoma schemas repair-plural-types
This coalesces plural types to the canonical singular form and declares the plural as an alias so existing references remain resolvable.
4. Clean up duplicate conversation entities from session UUID bridge — Claude Code users
Bug: Before the session UUID bridge fix, the Claude Code SessionStart hook and the MCP agent each created a separate conversation entity for the same session — one keyed by raw UUID, one by slug — that were never coalesced. (#145, #153, #256)
v0.13.0 prevents new duplicates automatically. To clean up historical ones, use the list_potential_duplicates MCP tool (or Inspector → Entities) to identify duplicate conversation pairs and merge them with merge_entities. This is cosmetic but improves timeline coherence and reduces entity count.
5. Encrypt existing data at rest — optional, self-hosted only
v0.13.0 ships db migrate-encryption for deployments that want to encrypt existing SQLite data. This is opt-in; the database is not encrypted by default.
neotoma db migrate-encryption encrypt
neotoma db migrate-encryption decrypt # reverses it
Requires NEOTOMA_KEY_FILE_PATH or NEOTOMA_MNEMONIC (+ optional NEOTOMA_MNEMONIC_PASSPHRASE). Both directions are idempotent.
6. Re-import harness transcripts to pick up previously missed conversations — optional
Bug: The transcript parser missed several conversation shapes across Claude Code, Codex, and Cursor (hex-encoded blobs, malformed JSON turns, state.vscdb format). Sessions imported before this release may be incomplete. (#143)
neotoma onboarding import-transcripts
The importer is idempotent — already-imported conversations are matched by stable identity and updated rather than duplicated.
Summary
| # | Command | Who should run it | Required? |
|---|---------|-------------------|-----------|
| 1 | neotoma db repair-schema-lag | All existing deployments | Recommended |
| 2 | neotoma db migrate-env-split | npm installs pre-dating v0.13.0 | Required if affected |
| 3 | neotoma schemas repair-plural-types | Anyone with plural entity type names | If applicable |
| 4 | Merge duplicate conversation entities via Inspector | Claude Code users | Cosmetic/optional |
| 5 | neotoma db migrate-encryption encrypt | Self-hosted, opt-in encryption | Optional |
| 6 | neotoma onboarding import-transcripts | Any harness transcript user | Optional |
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About markmhendrickson/neotoma
Deterministic state layer for AI agents. Stores versioned entities (contacts, tasks, transactions, decisions) with immutable observations, full provenance, and schema-first extraction. Local-first SQLite, cross-client memory across Claude, Cursor, ChatGPT, and OpenClaw. Website
Related context
Related tools
Earlier breaking changes
- v0.12.1 Inspector build prepublish now exits non-zero if inspector submodule is missing, breaking ad-hoc npm pack runs without init.
- v0.12.0 Access policy source precedence: env > SchemaMetadata.guest_access_policy > config
- v0.12.0 Legacy feedback subsystem completely removed; issues subsystem is replacement
- v0.12.0 MCP submit_issue requires reporter_git_sha or reporter_app_version
Beta — feedback welcome: [email protected]