Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "3.16.2"
".": "3.17.0"
}
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.17.0](https://github.com/dinglebear-ai/cortex/compare/v3.16.2...v3.17.0) (2026-09-30)


### Added

* add first-class install-cortex skill ([#249](https://github.com/dinglebear-ai/cortex/issues/249)) ([f708c51](https://github.com/dinglebear-ai/cortex/commit/f708c5118d3347531edc57220e9646512a30f94e))
* add session investigation evidence bundle ([#251](https://github.com/dinglebear-ai/cortex/issues/251)) ([d58f48b](https://github.com/dinglebear-ai/cortex/commit/d58f48ba7317a3f54dca9a78099120890450626e))
* **cortex:** expose bounded graph inventory and changes ([00ce2fa](https://github.com/dinglebear-ai/cortex/commit/00ce2fa5c311df8ddae247dbf955abf9052037d7))
* **cortex:** page session inventory metadata ([2155f23](https://github.com/dinglebear-ai/cortex/commit/2155f23f9a205bbdff4085229025eb919ee821b7))
* **plugin:** split installer and usage packages ([#270](https://github.com/dinglebear-ai/cortex/issues/270)) ([7619a23](https://github.com/dinglebear-ai/cortex/commit/7619a233484542a3f5eb03d563a80ab6d92c605b))
* **skills:** consolidate Cortex guidance and add Code Mode snippets ([4ace090](https://github.com/dinglebear-ai/cortex/commit/4ace090a000aee20b20ea176200927cf39244126))


### Fixed

* **cortex:** bound snippet evidence and search ([#259](https://github.com/dinglebear-ai/cortex/issues/259)) ([5b0da71](https://github.com/dinglebear-ai/cortex/commit/5b0da71ec5d24674aa5d3cd63022f9e566282e57))
* **db:** bound host-only log searches by index ([1ae5282](https://github.com/dinglebear-ai/cortex/commit/1ae52825717a03e1bb0feaa2b47f5e766b2bff79))
* **docs:** regenerate references from canonical inputs and enforce drift checks ([#273](https://github.com/dinglebear-ai/cortex/issues/273)) ([8d7de4a](https://github.com/dinglebear-ai/cortex/commit/8d7de4adc8e70dea5c37e118e00c5979039a962c))
* harden ingestion, recovery, and review qualification ([#244](https://github.com/dinglebear-ai/cortex/issues/244)) ([4455dc4](https://github.com/dinglebear-ai/cortex/commit/4455dc430c787984c2c8ee12246b2bd7e46a77a0))
* **ingest:** accept AI transcript archive replays ([#252](https://github.com/dinglebear-ai/cortex/issues/252)) ([a1a8443](https://github.com/dinglebear-ai/cortex/commit/a1a8443db32518d13740d1a6cbcf16009baa6d7b))
* **ingest:** accept corrected Codex speaker on exact replay ([#264](https://github.com/dinglebear-ai/cortex/issues/264)) ([c9c4a39](https://github.com/dinglebear-ai/cortex/commit/c9c4a39be6dfcc3ac36f6d77cebbaf8343623ddb))
* **ingest:** preserve structured tool and hook evidence from agents ([#263](https://github.com/dinglebear-ai/cortex/issues/263)) ([5c6e025](https://github.com/dinglebear-ai/cortex/commit/5c6e025307cde6f66725ec94668dd44d92a7568a))
* **ingest:** remediate comprehensive review findings ([#246](https://github.com/dinglebear-ai/cortex/issues/246)) ([12a41e9](https://github.com/dinglebear-ai/cortex/commit/12a41e9645ad17f121000bd1c4c4adb27fd6d88d))
* **ingest:** tolerate Codex project drift on exact replay ([#267](https://github.com/dinglebear-ai/cortex/issues/267)) ([a1642c4](https://github.com/dinglebear-ai/cortex/commit/a1642c4f3d7b552b9c33bfd775146dd18bd2834a))
* recover forwarded Claude skills and scope session search ([#248](https://github.com/dinglebear-ai/cortex/issues/248)) ([3b9855e](https://github.com/dinglebear-ai/cortex/commit/3b9855e01d0f539d24977731aafdb36ca5a78dd0))
* repair transcript skill evidence and search ([#247](https://github.com/dinglebear-ai/cortex/issues/247)) ([03ba04d](https://github.com/dinglebear-ai/cortex/commit/03ba04dfd406f1c9511a4bbd540d32e2002d973d))
* **transcripts:** accept equivalent Codex whitespace replays ([#269](https://github.com/dinglebear-ai/cortex/issues/269)) ([b484ac3](https://github.com/dinglebear-ai/cortex/commit/b484ac35d33183adaba1463b8b617b0317c67af6))

## [3.16.2](https://github.com/dinglebear-ai/cortex/compare/v3.16.1...v3.16.2) (2026-09-11)


Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ missing_safety_doc = "deny"

[package]
name = "cortex"
version = "3.16.2"
version = "3.17.0"
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ services:
# Default tag is kept in sync by `cargo xtask bump-version` (version canon);
# previously this was frozen at 1.0.0 while migrations moved forward —
# a stale binary against a newer schema (full-review OH1).
image: ghcr.io/dinglebear-ai/cortex:${CORTEX_VERSION:-3.16.2}
image: ghcr.io/dinglebear-ai/cortex:${CORTEX_VERSION:-3.17.0}
container_name: cortex
user: "${CORTEX_UID:-1000}:${CORTEX_GID:-1000}"
group_add:
Expand Down
2 changes: 1 addition & 1 deletion mcpb/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"manifest_version": "0.4",
"name": "cortex",
"display_name": "Cortex",
"version": "3.16.2",
"version": "3.17.0",
"description": "Self-hosted log aggregation and investigation for homelabs: syslog, Docker, OTLP, and AI transcripts in SQLite/FTS, exposed over MCP, CLI, and REST.",
"long_description": "cortex packages the existing cortex stdio entrypoint as a local MCP Bundle. It is query-only: it reads the configured SQLite database and does not start syslog listeners, HTTP servers, Docker Compose, REST, or deploy flows.",
"author": {
Expand Down
4 changes: 2 additions & 2 deletions packages/cortex-rmcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dinglebear/cortex",
"version": "3.16.2",
"version": "3.17.0",
"license": "AGPL-3.0-only",
"description": "Self-hosted log aggregation and investigation for homelabs: syslog, Docker, OTLP, and AI transcripts in SQLite/FTS, exposed over MCP, CLI, and REST.",
"homepage": "https://github.com/dinglebear-ai/cortex#readme",
Expand Down Expand Up @@ -55,7 +55,7 @@
"llm"
],
"mcpName": "ai.dinglebear/cortex",
"binaryVersion": "3.16.2",
"binaryVersion": "3.17.0",
"author": {
"name": "dinglebear.ai",
"url": "https://dinglebear.ai"
Expand Down
3 changes: 3 additions & 0 deletions release/components.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ version_files = [
{ kind = "regex_version", path = "server.json", pattern = '@dinglebear/cortex@(\d+\.\d+\.\d+)' },
{ kind = "regex_version", path = "server.json", pattern = '"placeholder": "v(\d+\.\d+\.\d+)"' },
{ kind = "json_version", path = "mcpb/manifest.json", json_pointer = "/version" },
# Upgrade qualification follows the same candidate as the release artifacts.
# Predecessor image digests remain explicit, independently verified pins.
{ kind = "json_version", path = "tests/live/contracts/releases/compatibility.json", json_pointer = "/candidate" },
# docker-compose.prod.yml default image tag: ${CORTEX_VERSION:-X.Y.Z}
{ kind = "regex_version", path = "docker-compose.prod.yml", pattern = 'CORTEX_VERSION:-(\d+\.\d+\.\d+)' },
{ kind = "changelog_heading", path = "CHANGELOG.md" },
Expand Down
12 changes: 6 additions & 6 deletions server.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "ai.dinglebear/cortex",
"title": "Cortex RMCP",
"description": "Self-hosted homelab log intelligence over MCP, CLI, and REST with SQLite/FTS.",
"version": "3.16.2",
"version": "3.17.0",
"websiteUrl": "https://github.com/dinglebear-ai/cortex",
"repository": {
"url": "https://github.com/dinglebear-ai/cortex",
Expand All @@ -25,7 +25,7 @@
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"identifier": "@dinglebear/cortex",
"version": "3.16.2",
"version": "3.17.0",
"runtimeHint": "npx",
"packageArguments": [
{
Expand Down Expand Up @@ -67,7 +67,7 @@
"format": "string",
"isRequired": false,
"isSecret": false,
"placeholder": "v3.16.2"
"placeholder": "v3.17.0"
},
{
"name": "CORTEX_RMCP_REPO",
Expand Down Expand Up @@ -105,12 +105,12 @@
"namespace": "ai.dinglebear",
"dnsDomain": "dinglebear.ai",
"distribution": {
"npm": "@dinglebear/cortex@3.16.2",
"npm": "@dinglebear/cortex@3.17.0",
"nodePackage": "@dinglebear/cortex",
"ociImage": "ghcr.io/dinglebear-ai/cortex:v3.16.2"
"ociImage": "ghcr.io/dinglebear-ai/cortex:v3.17.0"
},
"buildInfo": {
"version": "3.16.2",
"version": "3.17.0",
"repository": "https://github.com/dinglebear-ai/cortex"
}
}
Expand Down
8 changes: 4 additions & 4 deletions tests/live/contracts/releases/compatibility.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"schema": "cortex-live-upgrade-compatibility-v1",
"candidate": "3.16.2",
"candidate": "3.17.0",
"supported": {
"n_minus_1": {
"version": "3.16.1",
"version": "3.16.2",
"platform": "linux-amd64",
"origin": "ghcr.io/dinglebear-ai/cortex:v3.16.1",
"image": "ghcr.io/dinglebear-ai/cortex@sha256:348d126391226a017078b49d4c479ba5d593f66ac1cd9ce9cdf89ab8e53ef91b"
"origin": "ghcr.io/dinglebear-ai/cortex:v3.16.2",
"image": "ghcr.io/dinglebear-ai/cortex@sha256:32536072f4228255a8c98758296f46e2b723f3f53b0e56254b9a86e59fc8cbc7"
},
"oldest_scheduled": {
"version": "3.13.0",
Expand Down
4 changes: 4 additions & 0 deletions tests/live/phases/upgrade/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def validate(root):
if matrix['candidate'] != current:
raise ValueError(f'upgrade candidate {matrix["candidate"]} does not match Cargo version {current}; refresh predecessor pins')
version = lambda text: tuple(map(int, text.split('.')))
released = re.findall(r'^## \[(\d+\.\d+\.\d+)\]', (root / 'CHANGELOG.md').read_text(), re.MULTILINE)
predecessors = [entry for entry in released if version(entry) < version(current)]
if not predecessors or matrix['supported']['n_minus_1']['version'] != max(predecessors, key=version):
raise ValueError('upgrade n_minus_1 must match the previous release; refresh predecessor pins')
for entry in matrix['supported'].values():
if version(entry['version']) >= version(current):
raise ValueError('upgrade predecessor must precede candidate')
Expand Down
13 changes: 13 additions & 0 deletions tests/live/selftest/review-regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ def test_stale_upgrade_matrix_is_rejected(self):
with self.assertRaisesRegex(ValueError, 'does not match'):
module.validate(root)

def test_upgrade_matrix_requires_the_previous_release(self):
module = load('tests/live/phases/upgrade/validate.py')
with tempfile.TemporaryDirectory() as directory:
root = pathlib.Path(directory); dest = root / 'tests/live/contracts/releases'; dest.mkdir(parents=True)
for name in ['Cargo.toml', 'CHANGELOG.md']:
(root / name).write_text((ROOT / name).read_text())
matrix = json.loads((ROOT / 'tests/live/contracts/releases/compatibility.json').read_text())
# An immutable but older image is still not the immediate predecessor.
matrix['supported']['n_minus_1'] = matrix['supported']['oldest_scheduled'].copy()
(dest / 'compatibility.json').write_text(json.dumps(matrix))
with self.assertRaisesRegex(ValueError, 'previous release'):
module.validate(root)

def test_deployment_retry_uses_successful_revision_receipt(self):
with tempfile.TemporaryDirectory() as directory:
root = pathlib.Path(directory); tools = root / 'bin'; tools.mkdir()
Expand Down
2 changes: 1 addition & 1 deletion tests/live/services/oauth/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/live/surface-exporter/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion xtask/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "xtask"
version = "3.16.2"
version = "3.17.0"
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
Expand Down
40 changes: 40 additions & 0 deletions xtask/src/version_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,46 @@ version_files = [
check_release(root).unwrap();
}

#[test]
fn repository_version_sync_updates_upgrade_candidate_without_changing_predecessor_pins() {
use std::fs;
let source = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
let manifest = load_manifest(source).unwrap();
let component = sole_component(&manifest).unwrap();
let dir = tempfile::tempdir().unwrap();
let root = dir.path();
fs::create_dir(root.join("release")).unwrap();
fs::copy(
source.join("release/components.toml"),
root.join("release/components.toml"),
)
.unwrap();
for file in &component.version_files {
let destination = root.join(&file.path);
fs::create_dir_all(destination.parent().unwrap()).unwrap();
fs::copy(source.join(&file.path), destination).unwrap();
}
let matrix = root.join("tests/live/contracts/releases/compatibility.json");
let before: serde_json::Value =
serde_json::from_str(&fs::read_to_string(&matrix).unwrap()).unwrap();
let current = Version::parse(&read_version(root, &component.version_source).unwrap()).unwrap();
let next = Version::new(current.major, current.minor, current.patch + 1).to_string();
let cargo = root.join("Cargo.toml");
fs::write(
&cargo,
replace_cargo_package_version(&fs::read_to_string(&cargo).unwrap(), Some("cortex"), &next)
.unwrap(),
)
.unwrap();
assert!(check_sync(root).is_err());
sync_version(root).unwrap();
let after: serde_json::Value =
serde_json::from_str(&fs::read_to_string(&matrix).unwrap()).unwrap();
assert_eq!(after["candidate"], next);
assert_eq!(after["supported"], before["supported"]);
check_release(root).unwrap();
}

#[test]
fn drift_is_detected() {
use std::fs;
Expand Down
Loading