CortexDB 0.10.3 — order=recency honoured on leaf-scope answers, event-kind coverage, an answer cache, one-click updates, and a JSON error for every rejected request
0.10.3 is a fix release on top of 0.10.2, the last published release. Everything in
RELEASE_NOTES_0.10.2.md still applies; this page lists only what changed since, including the
work merged after 0.10.2 was cut (the answer cache, one-click updates, the directives.extract
fix and the best-practices guide). It adds no column family, directory or on-disk format, and
nothing is migrated: a 0.10.2 server opens and serves a data dir 0.10.3 has used (see "Rollback").
Summary
order: "recency"is honoured where it was silently ignored. From v0.9.0 to 0.10.2 the newest-first timeline tail ran only in theholisticview. Every/v1/answerover an exact scope with no child scopes recallsgranular, so an explicitorder: "recency"there, and on/v1/recallin any other view, was served ranked. It now serves the tail inholistic,granular,lineageandraw. An order/v1/answerinfers from the question ("latest", "currently", ...) takes the tail outsideholisticonly on a typed event stream (most of the newest events carrycontext.intent); conversation scopes stay ranked, as before.- Event streams keep their rare events in the answer context. On a scope whose events carry
context.intent, the answer context keeps the newest event of each kind (an order cancellation 700 events behind a burst of page views), after a[note] Older history:line, and a question that names a kind gets that kind's newest event. - An over-budget timeline tail loses its oldest events, not its newest, and stays newest-first.
- The premise guard no longer discards correct answers about a scope's own subject, and an abstention may now carry the absence report that led to it.
- Measured on a 115-question customer-journey regression set (typed event streams, the
customer's own request shape through the API, no
view): 81 correct on 0.10.2, 114 on 0.10.3. - Answer cache (opt-in,
CORTEX_ANSWER_CACHE=1): a repeated question returns the stored answer without recall or a model call, only while it is provably current. - One-click updates (opt-in): the admin console can install a release through an updater sidecar that backs up the data first and rolls back a failed update.
directives.extractis honoured on single captures, so "search only" captures stop running every enrichment stage.- Every request the server refuses before its handler runs gets the JSON error envelope
(an unknown field, malformed JSON, a wrong
Content-Type, a bad query string or path), with the status it always had and the request's own id. - No background LLM spend with enrichment off: the scheduler's compaction pass no longer calls
the consolidation model when
CORTEX_ENRICHMENT_DELAY_SECONDSis unset. - Operator fixes: failed requests' log lines carry
error_codeandretriable;uptime_secondscounts from process start;scripts/cold_backup.pyrefuses links, devices and escaping paths; the startup lint's RAM line is fixed. - One client change: the TypeScript SDK 0.10.1 adds the
extractandanswer_cachetypes. Every other client released with 0.10.1 works against 0.10.3 unchanged.
Upgrade from 0.10.2
Before you upgrade: what clients and operators will notice
/v1/answercallers that send noviewon exact scopes with no child scopes (most direct API integrations; the SDKs and the CLI sendview: "holistic"by default and are not affected by this item):- an explicit
order: "recency"now serves the timeline tail, the scope's newestbudgets.per_layer_limits.eventsevents (defaultCORTEX_RECENCY_TAIL_EVENTS, 100), in place of ranked retrieval. Evidence older than those events is then not in the context, apart from the event-kind additions below; - a recency-shaped question ("recent", "latest", "newest", "currently", "next best action")
without
ordertakes the tail only when the scope is a typed event stream: more than half of its newest events carrycontext.intent. On every other scope (chat histories, documents) the answer stays ranked, exactly as in 0.10.2. - To keep 0.10.2's ranked behaviour on one request, send
order: "relevance"; for the whole server, setCORTEX_RECENCY_INFERENCE=0(inferred order) orCORTEX_RECENCY_ORDER=0(the tail itself).
- an explicit
/v1/recallwithorder: "recency"andviewgranular,raworlineagenow returns the newest-K tail; it returned ranked events before. Arawtail fillslayers.eventsonly.descendandstructuredstay ranked.- A timeline tail that names none of the question's capitalised names (for example "Trek" in
"how often do I ride the Trek?") is no longer served as an empty context: ranked retrieval runs
instead. This applies to every view,
holisticincluded. - Answers on typed event streams read more, and cost a little more. Where the tail now
replaces ranked retrieval it fills the answer context up to
budgets.max_tokens(default 4,000, at most 8,000), which a ranked context often did not. Event-kind coverage then costs one more bounded read of the scope's own events (at most 8 pages of 1,024) on each answer that uses it; its entries take the place of the oldest tail events, so the context never exceedsbudgets.max_tokens. On the regression set above, an answer used about 7 % more input tokens (7,434 against 6,957) and 11 % more output tokens (291 against 261), and finished sooner (p50 4.9 s against 5.6 s). Scopes whose events carry nocontext.intentare unaffected. - The answer context of a typed event stream can end in
[note] Older history: ...followed by the newest event of each kind the newest events do not include (CORTEX_ANSWER_KIND_COVERAGE=0turns this off). Scopes whose events carry nocontext.intentare unchanged. - An abstention can carry a trailing absence report: "The information provided is not enough. The memories contain no record of the user viewing a Model X widget." Match an abstention by its leading "The information provided is not enough.", never by equality with that sentence.
- Events, recall items and exports carry
extract(the stages the capture'sdirectives.extractallowed) when the capture set one. A client that validates events against a closed schema must accept the field. Events written before 0.10.3 carry none. - Servers with enrichment off stop background consolidation.
CORTEX_CONSOLIDATION_ENABLEDnow defaults to following enrichment: withCORTEX_ENRICHMENT_DELAY_SECONDSunset, the scheduler's compaction pass runs no memory consolidation, knowledge synthesis or concept abstraction (no LLM call). SetCORTEX_CONSOLIDATION_ENABLED=1to keep them. Each pass logsllm_stages(enabled,explicitorenrichment_unset). - Rejected requests answer JSON, not plain text. Statuses do not change:
422 INVALID_BODYfor a body that does not fit the route (unknown field, wrong type, missing field),400 INVALID_BODYfor a body that is not JSON or could not be read,415 UNSUPPORTED_MEDIA_TYPE,400 INVALID_QUERY,400 INVALID_PATH_PARAMS, andINVALID_REQUESTfor any other plain-text 400 or 422. A client that parsed the plain text must read the envelope'smessage(it keeps the same words). The SDKs now raise these codes instead ofUNKNOWN. - The request log line of a failed request carries
error_codeandretriable. A log pipeline that parses the line's fields sees two more on non-2xx lines. /v1/admin/metricsuptime_secondscounts from process start, not from the first metered request.scripts/cold_backup.pyrefuses more.backupexits 2 when the data dir holds a symbolic link or a special file (it names them);restoreandverifyexit 4 on an archive member that is a link, a device or a FIFO, or whose path is absolute or leaves the target, and on an archive with no manifest. Restored files now belong to the user running the restore (root under sudo), not to the owners recorded in the archive:chownthe restored dir to the server's user before starting it (chown -R 1000:1000for the image'scortexuser;chown -R --reference=<old data dir>for a systemd unit).restoreprints the owners the archive recorded.- Nothing changes unless you opt in for the answer cache (
CORTEX_ANSWER_CACHE) and one-click updates (thedocker-compose.updater.ymloverlay).
Upgrade steps
Nothing is migrated and there is nothing to run afterwards. Replace the binary or image and restart as for any release, giving the server 120 s to stop. Then check:
GET /v1/admin/version:crate_version0.10.3 and thegit_shayou deployed. The capability list is the same 11 names as 0.10.2.GET /v1/admin/ready:ready: true.- With enrichment off and the background scheduler on, the compaction log line reports
llm_stages="enrichment_unset"; setCORTEX_CONSOLIDATION_ENABLED=1if you relied on consolidation. - If your client calls
/v1/answerwithoutviewon event-stream scopes and wants ranked answers, sendorder: "relevance".
Upgrading from 0.10.1 or v0.9.13
0.10.3 contains everything in 0.10.2. Read RELEASE_NOTES_0.10.2.md, "Upgrade from 0.10.1"
(and from there RELEASE_NOTES_0.10.1.md for v0.9.13) first; this page applies on top.
What changed
Recall and answer: order: "recency" in every view that reads the scope's own events
order: "recency" replaces ranked retrieval for the events layer with the scope's newest eligible
events by observed_at, newest first, with the same eligibility as ranked mode (scope, tenant,
filters, time window, forgets, cancels). Since v0.9.0 it ran only in holistic, and /v1/answer
recalls an exact scope with no child scopes granular, so both an explicit and an inferred order
were dropped there without a trace. 0.10.3:
| Recall view | Explicit order: "recency" | Order inferred by /v1/answer |
|---|---|---|
holistic | tail (as before) | tail (as before) |
granular (the leaf-scope answer view), lineage | tail (was ranked) | tail on a typed event stream, else ranked (as before) |
raw (/v1/recall only) | tail in layers.events, no context block (was ranked) | n/a |
descend, structured | ranked | ranked |
A typed event stream is a scope where more than half of the tail's events carry a non-empty
context.intent. The inferred tail is limited to them because a cue word says nothing about where
a conversation's evidence is: in a chat history, "which bike am I currently riding?" is answered
by a turn from weeks ago, not by the newest 100 turns (measured on LongMemEval below). A tail the
entity grounding gate would clear (no event names the question's capitalised names) falls back to
ranked retrieval instead of an empty context, in every view.
Answer: the over-budget cut keeps the newest events
The answer context is capped at budgets.max_tokens (default 4,000, at most 8,000). A timeline
tail longer than that now keeps its newest-first order and loses its oldest events. Before, the
cap re-ranked the tail by evidence type, could drop its newest event, and still told the model the
context was newest-first.
Answer: event-kind coverage (CORTEX_ANSWER_KIND_COVERAGE, default on)
On a scope whose events carry context.intent, /v1/answer reads the scope's kind census: the
newest eligible event of each distinct intent (at most 32 kinds; a scope with more gets none),
under the recall's scope, view, filters and time window. The census is one bounded read of the
scope's own events (at most 8 pages of 1,024; a scope whose events do not fit gets none). It is
skipped for use_pack_id, for an answer that descended into child scopes and on native reads.
- Over a timeline tail, the context keeps the newest events that fit and then, after
[note] Older history: ..., the newest event of each kind those do not include. Each is older than every event above the note, so the context stays newest-first, and the whole stays withinbudgets.max_tokens. - Over a ranked context, when the question names a kind (a word of the intent: "order" names
shop.order.cancel, unless every kind of the scope carries that word), the newest event of each named kind is added.
Events without an intent have no kind, so a scope without intents is unchanged.
Answer: premise guard
When an answer asserts something but also says the memories do not mention what the question
presupposes, /v1/answer replaces it with "The information provided is not enough." Changes:
- A note that the request scope's own identifier does not appear in the memory text ("no record of
the user id
<id>" over scope.../user:<id>) no longer triggers it: every recalled memory belongs to the scope. - When the answer opens with a plain absence report about the asked thing, that clause is kept after the abstention. The clause ends at the first comma, dash, semicolon or sentence end, and a leading "No" and everything after the clause are dropped, so the result is still an abstention, never a negative answer ("No, there is no record of who you went with, you went alone" keeps only "There is no record of who you went with").
- A question that names the scope's own identifier gets a prompt note that the memories are that subject's history.
Answer cache (opt-in)
With CORTEX_ANSWER_CACHE=1, a repeated /v1/answer from the same caller and token, in the same
scope and view, with the same answer-shaping fields (and the same UTC day when the request has no
question_date), returns the stored response without recall or a model call, while it is
provably current:
- A write at the scope, below it or at a read ancestor (including one up to 5 s before the answer started), any forget, erasure, cancel or redact, or an ACL change invalidates it; a scope migration, a conflict resolution and a live feature toggle clear the cache.
- A response is stored only when indexing was current and no evidence source was degraded,
including an answer started while the scope-partition map was still building after a restart
(
scope_partition_map, below). CORTEX_ANSWER_CACHE_TTL_SECS(default 300, at most 540),CORTEX_ANSWER_CACHE_MAX(default 1,000 entries). Held in memory only.Cache-Control: no-cacheanswers now and replaces the stored answer;no-storeneither reads nor writes. Streams,skip_answer_llm,use_pack_idand facet-plan overrides bypass it.x-cortex-answer-cache: hit | miss | bypasson every 2xx while it is on;diagnostics.answer_cache(hit,age_ms) on a hit, wheretokens_inputandtokens_outputread 0; ananswer_cacheblock of counters onGET /v1/admin/metrics.- Inert on the legacy WAL (
CORTEX_UNIFIED_WAL=0), with a startup warning.
One-click updates (opt-in)
docker-compose.updater.yml adds an updater sidecar, the only container with the Docker socket,
with no published port. With CORTEX_UPDATER_URL and CORTEX_UPDATER_TOKEN set, the admin
console's Updates page offers Update now: POST /internal/ui/update asks the sidecar to check
the data is on a volume, pull the release while serving, take a cold backup of the data, stop the
server gracefully, recreate it on the new image with the same settings, wait for health, and roll
back on failure. It refuses an older version (422 DOWNGRADE_REFUSED) and answers
503 UPDATER_NOT_CONFIGURED without a sidecar. docs/PRODUCTION_DEPLOYMENT.md has the setup, and
TELEMETRY.md describes the one new call (to the sidecar on the compose network; CortexDB makes no
new outbound call).
directives.extract on single captures
A POST /v1/experience under the unified WAL lost directives.extract when the indexer rebuilt
the request from the stored event, so a "search only" capture ran every enrichment stage. The
directive is now stored on the event (extract, omitted when absent), honoured by the indexer,
returned on events, recall items and /v1/export, and restored by /v1/import/jsonl. Events
written before 0.10.3 carry none and are not repaired. Triples are always extract-none.
Recall: scope_partition_map degraded source
After a restart over a large store the server builds its scope-partition map in the background.
Until it lands, descendant listings and cold-tier vector scans come back empty without an error.
Recall now names a scope_partition_map: ... entry in diagnostics.degraded_sources (for a
caller that may read diagnostics), /v1/answer reports the scope_partition_map code to every
caller, and the answer cache never stores such an answer.
Errors: the envelope for every rejected request
A request whose body, query string or path parameter the route's extractor could not read was
answered with a plain-text body. It now gets the error envelope (error_code, message,
request_id, retriable: false, details.part, details.reason; /v1/answer and
/v1/recall/stream add details.field_path), with the status unchanged (table below). The
envelope's request_id and the X-Request-Id header are the request's own id: the client's when
it sent one, else the one the server minted for the request, which is also the id of the request
log line and of the authentication layer's audit row. The 413 of an oversized body does the same.
Operations
- Request log: a line for a response outside 2xx whose body is the error envelope carries its
error_codeandretriable(never its message); both are absent on 2xx and non-envelope bodies. - Compaction LLM stages follow enrichment unless
CORTEX_CONSOLIDATION_ENABLEDsays otherwise (see "Before you upgrade"). The deterministic stages (fact compaction, communities, procedures) are unchanged. uptime_secondsonGET /v1/admin/metricscounts from process start.- Startup lint: on hosts at or below the RAM model's ~18 GiB baseline it says the model has no
estimate, instead of "fits roughly 0M hot vectors"; counts print as
488k/44.9M. scripts/cold_backup.py: see "Before you upgrade". Extraction uses Python'starfiledatafilter where it exists and otherwise writes the checked members itself; it never extracts fully trusted. A missing manifest is exit 4 instead of a traceback.
Docs
docs/BEST_PRACTICES.md (ingestion, embeddings, what runs on-prem, answer reuse, staying current,
launch checklist), the embedding migration runbook and the production deployment guide are in the
admin console's docs. The API reference documents all of the above, and docs/schemas/openapi.json
adds order to /v1/recall, the answer cache headers and metrics, and the stored extract.
Fixes
order: "recency"was ignored on every leaf-scope/v1/answerand on/v1/recalloutsideholistic, explicit or inferred, with no diagnostic (since v0.9.0). It is now served in every view that reads the scope's own events (above).- An over-budget recency tail was re-ranked by evidence type by the answer packer and could lose its newest event. It is now cut oldest-first.
- A recency tail with none of the question's names was cleared by the grounding gate and served as an empty context. Ranked retrieval now runs instead.
- The premise guard turned correct answers into abstentions when the model remarked that the scope's own id does not appear in the memory text. The scope's own id no longer counts as a missing premise.
directives.extractwas lost on single captures under the unified WAL, so they ran every enrichment stage. It is stored on the event and honoured.- Extractor rejections answered plain text (an unknown field, malformed JSON, a bad query string or path; a 0.10.2 known issue). They answer the JSON envelope with the request's own id.
- The scheduler's compaction pass called the consolidation model with enrichment off. It
makes no LLM call unless
CORTEX_CONSOLIDATION_ENABLED=1. uptime_secondscounted from the first metered request, and the startup lint printed "fits roughly 0M hot vectors" on hosts with less than ~18 GiB of RAM. Both are fixed.scripts/cold_backup.pyarchived a symbolic link's target, silently skipped the contents of a symlinked directory, and on Python before 3.14 extracted archives fully trusted (links and devices included). Backup now refuses and names such entries; restore extracts checked members only.
Measurements
Measured against the published 0.10.2 image, one host per test. Unless a paragraph says otherwise, the figures come from the 0.10.3 release candidate before its review fixes; the last section checks the final build against it.
A customer-journey regression set
115 questions over typed event streams (page views, transactions, cancellations and chats per
end user), graded by a model judge, sent through the API exactly as the customer's integration
sends them (no view):
| Questions | 0.10.2 | 0.10.3 |
|---|---|---|
| Recommendations: what the user is likely to want next (12) | 0 | 12 |
| Names of recent events (12) | 5 | 11 |
| Summary of the user's recent activity (12) | 5 | 12 |
| Event linked to a conversation (4) | 1 | 4 |
| Did the user ever ... (absence, 10) | 7 | 10 |
| Next best action (11) | 10 | 11 |
| Transaction activity (11) | 10 | 11 |
| Activity in a time window, latest activity, latest chat, latest conversation, recently viewed items (43) | 43 | 43 |
| Total (115) | 81 | 114 |
The best earlier run of the same set (a v0.8.x build, July 2026) was also 114. The recency tail served 83 of the 115 questions (none on 0.10.2). The one miss listed one event name more than the expected answer; its prompt is token-identical to two earlier runs of the same change that scored 115 of 115, so it is answer-model or judge variance.
With the customer's console request shape (view: "holistic", where 0.10.2 already served the
tail): 0.10.2 answered 111 of 115. 0.10.3 answered all 77 questions of the eight categories where
0.10.2 had failed any (0.10.2: 73 of the same 77); the other 38, all correct on 0.10.2, were not
re-run.
Per answer, no view: about 7,434 input and 291 output tokens (0.10.2: 6,957 and 261); with the
answer model used, $0.0445 against $0.0413. Latency with 4 concurrent clients: p50 4.9 s, p90
8.9 s, p99 10.9 s (0.10.2: p50 5.6 s, p90 10.2 s).
Conversation histories (LongMemEval)
The inferred tail must not reach chat histories. On the 38 LongMemEval questions that carry a recency cue ("currently", "recent", "latest", "most recent"), a build that applied the inferred tail everywhere answered 17 of them from the newest 100 turns, and their contexts held 0 of 42 gold evidence turns (0.10.2: 39 of 42). 0.10.3 serves those 17 no tail: 15 of 17 contexts are byte-identical to 0.10.2's and the other 2 hold the same evidence (37 of 42 gold turns in context on both, on a store built for this check). Answers were not re-run on the final build.
On the 30 abstention questions (one store, both binaries, the same answer configuration), no answer changed because of the premise-guard change on the release candidate; the other differences between the two runs had byte-identical contexts (answer-model variance).
Indexed captures under forgets
4 CPUs, 3 GB, real disk syncs, two pairs of runs in reversed order: new-scope wait=indexed p50
77 ms on both; p99 287 ms against 279 ms on 0.10.2 (+7.7 ms, +2.8 %; 95 % bootstrap interval
-0.1 to +15 ms). Without forgets p99 was 5.5 ms lower on 0.10.3. No write took over 1 s and every
write answered 200.
Other checks
The live Docker suite (six scenarios), the multilingual smoke (42 of 42), the upgrade and rollback
probe (72 of 72, "Rollback"), the enrichment-off compaction check (31 LLM calls over 3 passes on
0.10.2, 0 on 0.10.3, 31 again with CORTEX_CONSOLIDATION_ENABLED=1), the rejected-request
envelopes and their log fields (8 of 8 failed requests logged with error_code; 0 on 0.10.2), and
uptime_seconds.
The final build
The review fixes (the inferred-tail restriction, the tail grounding fallback, the absence-report
clause cut and the rejected requests' ids) were checked without answer-model calls
(skip_answer_llm) against the candidate on the same stores. On the customer-journey set the
answer context of 114 of 115 questions is byte-identical to the candidate's in both request
shapes, and the tail serves the same 83 (no view) and 85 (view: "holistic") questions; the
115th context is ranked and also differs between two runs of the candidate itself. That question
is the only one whose candidate answer the clause cut shortens; it answered correctly in 2 of 2
runs on the final build. The release commits after the final build change documentation only.
Environment variables
| Variable | Change |
|---|---|
CORTEX_ANSWER_CACHE | New. 1 turns the answer cache on (default off). |
CORTEX_ANSWER_CACHE_TTL_SECS | New. Default 300, at most 540. |
CORTEX_ANSWER_CACHE_MAX | New. Default 1,000 entries, at most 100,000. |
CORTEX_ANSWER_KIND_COVERAGE | New. Event-kind coverage, default on; 0/off/false turns it off. |
CORTEX_UPDATER_URL, CORTEX_UPDATER_TOKEN | New. The updater sidecar and its shared token. |
CORTEX_CONSOLIDATION_ENABLED | Unset now follows enrichment (was: on). 1 opts in; 0/false/off turns consolidation off. |
CORTEX_RECENCY_ORDER | Unchanged switch; the tail it controls now serves granular, lineage and raw too. |
CORTEX_RECENCY_INFERENCE | Unchanged switch; an inferred order outside holistic takes the tail only on typed event streams. |
docs/generated/env-vars.md has the full rows.
Error codes
| HTTP | Code | Where | Change | Retriable |
|---|---|---|---|---|
| 400 | INVALID_BODY | any v1 route that reads a JSON body | Was a plain-text 400: the body is not JSON, has trailing bytes, could not be read or is not UTF-8. | no |
| 400 | INVALID_QUERY | routes with a query string | New: a query parameter that does not parse, or a missing required one. A repeated ?scope= on GET /v1/events/{id} is one. | no |
| 400 | INVALID_PATH_PARAMS | routes with a path parameter | New: a path parameter that does not parse. | no |
| 400, 422 | INVALID_REQUEST | any v1 route | New: any other plain-text 400 or 422. | no |
| 415 | UNSUPPORTED_MEDIA_TYPE | routes with a JSON body | Was plain text: a missing or non-JSON Content-Type. | no |
| 422 | INVALID_BODY | routes with a JSON body | Was plain text on most routes: an unknown field, a wrong type, a missing field. | no |
| 422 | DOWNGRADE_REFUSED | POST /internal/ui/update | New. | no |
| 503 | UPDATER_NOT_CONFIGURED | POST /internal/ui/update | New. | no |
Startup warnings
CORTEX_ANSWER_CACHE is on, but this server runs the legacy WAL (CORTEX_UNIFIED_WAL=0), which has no indexing watermark; answers are never stored: the cache is set but cannot store.- The
CORTEX_VECTOR_RESIDENT_MAX is unsetlint now says that a host at or below the RAM model's ~18 GiB baseline gets no estimate, instead of "fits roughly 0M hot vectors".
Rollback
0.10.3 adds no column family, directory or on-disk format. To roll back, stop 0.10.3 with the usual
120 s grace and start 0.10.2 on the same data dir. A rollback brings back 0.10.2's behaviour,
including the issues this release fixes. 0.10.2 ignores the stored extract directive, so an
event it indexes after the rollback runs every stage again; the answer cache, held in memory, is
gone with the process.
What was checked, on one data dir, with a graceful stop between each step (on the release candidate before the review fixes, which change no storage code):
- 0.10.2 wrote English, Devanagari and Hinglish captures, a 32 KB turn, a 13 KB event captured on someone else's behalf and a 200-item bulk, and ran a forget-all and a forget by id.
- 0.10.3 read all of it, wrote single captures, a 300-item bulk and a multi-chunk Hindi document, and ran a forget-all and a forget by id.
- 0.10.2 again opened the store and served everything 0.10.3 had written (the bulk samples, the long document by id); what 0.10.3 had forgotten stayed gone. It wrote, bulk-wrote 100 items and forgot the document by id.
- 0.10.3 again read everything, including the writes made during the rollback, and the forgotten items stayed gone.
Every phase stopped cleanly and logged no error. After each phase the column families of every
RocksDB store and the data dir's top-level entries were listed: 0.10.3 added none, before or after
the rollback (72 of 72 checks). A rollback from 0.10.3 to 0.10.1 or v0.9.13 was not re-run; 0.10.3
stores nothing 0.10.2 does not, so RELEASE_NOTES_0.10.2.md, "Rollback", describes it.
Known issues
New or changed in 0.10.3:
- An inferred timeline tail on a typed event stream still replaces ranked retrieval. A
recency-shaped question there gets the newest events (plus the kind exemplars) even when it is
about an older one. Send
order: "relevance"for such questions. - The typed-event-stream test is a heuristic: a conversation integration that sets
context.intenton most messages gets the inferred tail too. Sendorder: "relevance", or setCORTEX_RECENCY_INFERENCE=0. budgets.max_tokensdoes not cap a/v1/recalltail. An explicitorder: "recency"ingranular,raworlineageserves the tail asholisticalways has, up toCORTEX_SMALL_SCOPE_EXHAUSTIVE_MAX_TOKENSor the tail size, whichever is smaller./v1/answerstill cuts its context tobudgets.max_tokens.- Tail and kind-coverage entries carry no timestamp prefix, so a "when" question over a conversation tail sees no dates unless the text has them.
- A
lineagetail lists the request scope's own events (plus recent writes, through the recent-write supplement): the ancestors' older events are not in it. Sendorder: "relevance"for a lineage read that needs them. prefer_exhaustiveis ignored on leaf scopes: the whole-corpus probe runs only inholistic, and an exact-scope answer recallsgranular.- CORS does not expose
x-cortex-answer-cacheor allow theCache-Controlrequest header, so a browser client cannot read or set them across origins. - The startup lint sizes RAM from the host's
MemTotal, not a container memory limit. - Consolidation's entity-extractor calls are not booked in
GET /v1/admin/usage: withCORTEX_CONSOLIDATION_ENABLEDon, only the consolidation calls themselves appear.
Carried over from 0.10.2 (still present in 0.10.3):
/v1/answeraccepts unknown body fields (200, the field ignored);/v1/recallanswers malformed JSON with422 INVALID_BODY, not400, and accepts a body with noContent-Type.- A
413for an oversized body has no CORS headers. wait=indexedwaits for the whole log, not for the capture's own event; a storm of new scopes inside a forgotten subtree still blocks the forget; forgets contend with long-document fragment locks. All three are known and deferred.- Everything else under "Known issues" in
RELEASE_NOTES_0.10.2.md, except the plain-text 422, which 0.10.3 fixes.
Clients
- TypeScript SDK
cortexdbai0.10.1 (npm, from 0.10.0): types only.ExtractStageis exported,RecallEventFields.extract(ExtractStage[]) is on events and recall items, andAnswerResponse.diagnostics.answer_cache(hit,age_ms) on a cached answer. No runtime change. - Python SDK
cortexdbai0.12.0,cortexdb-mcp0.8.0,cortexdb-cli0.6.0 andcortexdb-connectors0.2.22 are unchanged and work against 0.10.3. What they will see:- a rejected request (
400,415,422before the route runs) now raises with the server'serror_code(INVALID_BODY,INVALID_QUERY, ...) instead ofUNKNOWN, still as the baseV1APIError, so existing handlers keep working; - the SDKs and the CLI send
view: "holistic"onanswerby default, so their inferred recency behaves as in 0.10.2; only a recency tail that names none of the question's capitalised names now falls back to ranked retrieval. None of them exposesorderyet; - code that compares an answer with "The information provided is not enough." must match the prefix (see "Before you upgrade");
- the connectors classify errors by HTTP status, so the envelope change is transparent to them.
- a rejected request (
Notes
Single-node remains the only supported topology.