From 01b984d16d72b51a64fb2460413f44a609f80d8a Mon Sep 17 00:00:00 2001 From: jmagar <38927646+jmagar@users.noreply.github.com> Date: Wed, 30 Sep 2026 09:08:37 -0400 Subject: [PATCH 1/3] chore(main): release 3.17.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- mcpb/manifest.json | 2 +- packages/cortex-rmcp/package.json | 4 ++-- server.json | 2 +- xtask/Cargo.toml | 2 +- 8 files changed, 37 insertions(+), 9 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a785d763b..a2914e522 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.16.2" + ".": "3.17.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 36c15385c..80a412d8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/Cargo.lock b/Cargo.lock index 3644b0859..f18799fb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -534,7 +534,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cortex" -version = "3.16.2" +version = "3.17.0" dependencies = [ "anyhow", "async-stream", @@ -4577,7 +4577,7 @@ checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "xtask" -version = "3.16.2" +version = "3.17.0" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index af3aec157..d63551346 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/mcpb/manifest.json b/mcpb/manifest.json index 8cde2101c..0a9120bda 100644 --- a/mcpb/manifest.json +++ b/mcpb/manifest.json @@ -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": { diff --git a/packages/cortex-rmcp/package.json b/packages/cortex-rmcp/package.json index 75ef696dd..5311802fe 100644 --- a/packages/cortex-rmcp/package.json +++ b/packages/cortex-rmcp/package.json @@ -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", @@ -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" diff --git a/server.json b/server.json index afea76e58..9c32d3c1e 100644 --- a/server.json +++ b/server.json @@ -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", diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 5189cf3d0..83b0702a7 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -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 From 770dca830698c78b06be40064e76a8e2a11728b8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Sep 2026 13:09:41 +0000 Subject: [PATCH 2/3] chore: sync version carriers release-please cannot reach --- docker-compose.prod.yml | 2 +- server.json | 10 +++++----- tests/live/services/oauth/Cargo.lock | 2 +- tests/live/surface-exporter/Cargo.lock | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index caee0a5be..7070b0fe9 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -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: diff --git a/server.json b/server.json index 9c32d3c1e..aceebd705 100644 --- a/server.json +++ b/server.json @@ -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": [ { @@ -67,7 +67,7 @@ "format": "string", "isRequired": false, "isSecret": false, - "placeholder": "v3.16.2" + "placeholder": "v3.17.0" }, { "name": "CORTEX_RMCP_REPO", @@ -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" } } diff --git a/tests/live/services/oauth/Cargo.lock b/tests/live/services/oauth/Cargo.lock index e0b47299d..63bf543da 100644 --- a/tests/live/services/oauth/Cargo.lock +++ b/tests/live/services/oauth/Cargo.lock @@ -434,7 +434,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cortex" -version = "3.16.2" +version = "3.17.0" dependencies = [ "anyhow", "async-stream", diff --git a/tests/live/surface-exporter/Cargo.lock b/tests/live/surface-exporter/Cargo.lock index ec7b8d5ca..807537604 100644 --- a/tests/live/surface-exporter/Cargo.lock +++ b/tests/live/surface-exporter/Cargo.lock @@ -434,7 +434,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cortex" -version = "3.16.2" +version = "3.17.0" dependencies = [ "anyhow", "async-stream", From cdb4e7112ce55a6c269ef0612955c01fdae5affa Mon Sep 17 00:00:00 2001 From: Jake Magar Date: Wed, 30 Sep 2026 01:23:38 -0400 Subject: [PATCH 3/3] fix(release): synchronize upgrade qualification version carriers --- release/components.toml | 3 ++ .../contracts/releases/compatibility.json | 8 ++-- tests/live/phases/upgrade/validate.py | 4 ++ tests/live/selftest/review-regressions.py | 13 ++++++ xtask/src/version_tests.rs | 40 +++++++++++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/release/components.toml b/release/components.toml index 0ab3801b2..df5524639 100644 --- a/release/components.toml +++ b/release/components.toml @@ -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" }, diff --git a/tests/live/contracts/releases/compatibility.json b/tests/live/contracts/releases/compatibility.json index 5a679068e..557a92747 100644 --- a/tests/live/contracts/releases/compatibility.json +++ b/tests/live/contracts/releases/compatibility.json @@ -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", diff --git a/tests/live/phases/upgrade/validate.py b/tests/live/phases/upgrade/validate.py index 2226d7c13..150d6f35b 100644 --- a/tests/live/phases/upgrade/validate.py +++ b/tests/live/phases/upgrade/validate.py @@ -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') diff --git a/tests/live/selftest/review-regressions.py b/tests/live/selftest/review-regressions.py index fed6a2656..5efd7ce58 100644 --- a/tests/live/selftest/review-regressions.py +++ b/tests/live/selftest/review-regressions.py @@ -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() diff --git a/xtask/src/version_tests.rs b/xtask/src/version_tests.rs index 9690cd261..19bce0f43 100644 --- a/xtask/src/version_tests.rs +++ b/xtask/src/version_tests.rs @@ -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;