Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ body:
attributes:
label: Affected commit SHA
description: Exact LCM-X commit that exhibits the bug. Add a branch or release tag only as context.
placeholder: Exact commit SHA for v0.23.0-rc1 or main, for example 0123456789abcdef...
placeholder: Exact commit SHA for v0.23.2 or main, for example 0123456789abcdef...
validations:
required: true

Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ version tags but does not have a destination GitHub Release object for RC2.

## Unreleased

## v0.23.2 - security + lossless point release

- Lossless by default: durable sensitive-pattern redaction (`LCM_SENSITIVE_PATTERNS_ENABLED`,
default off) is now fully independent of cloud-embedding privacy. Known cloud providers
protect only the provider-bound copy, controlled by the new `LCM_EMBEDDING_PRIVACY_ENABLED`
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,15 @@ default-off experimental features.
independent — see "Sensitive-pattern redaction" below.)

Stable release identity and the continuing `main` development line are
separate proof planes. The source snapshot used for the current reconciliation
is `main@3d4fbb4c979dc09aef0b831bb50d928e0e18d68f`; do not describe an
arbitrary main checkout as the installed stable product.
separate proof planes; do not describe an arbitrary `main` checkout as the
installed stable product.

That exact development baseline still identifies itself as
`hermes-lcm v0.23.0-rc1 (15 tools)`. The stable tag identifies itself as
`hermes-lcm v0.23.1 (15 tools)`. This is tracked as a deferred version-policy
decision rather than being silently restamped by documentation changes.
The reconciled `main` line now identifies itself as
`hermes-lcm v0.23.2 (15 tools)` — aligned forward from the `v0.23.1` stable
tag, which identifies itself as `hermes-lcm v0.23.1 (15 tools)`. This resolves
the earlier drift where `main` declared an older release candidate than the
shipped stable tag (#385); it is a forward bump, never a restamp of any past
commit's own recorded identity.

Eva has accepted exact stable v0.23.1 with hosted `voyage-4-large`,
1024-dimensional float32 summary vectors under one privacy-bound identity.
Expand Down Expand Up @@ -253,7 +254,7 @@ Provider Plugins:
```

An untagged checkout of the reconciled `main` baseline instead reports
`hermes-lcm v0.23.0-rc1 (15 tools)`; verify the loaded commit before treating
`hermes-lcm v0.23.2 (15 tools)`; verify the loaded commit before treating
either string as release proof.

For source checkouts, `lcm_status`, `/lcm status`, `lcm_inspect`,
Expand Down
7 changes: 5 additions & 2 deletions docs/operator-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,11 @@ Provider Plugins:
```

An untagged checkout of the reconciled `main` baseline instead reports
`hermes-lcm v0.23.0-rc1 (15 tools)`. Version text alone is not release proof;
verify the loaded commit and tag.
`hermes-lcm v0.23.2 (15 tools)`. Version text alone is not release proof;
Comment thread
100yenadmin marked this conversation as resolved.
Resolved
verify the loaded commit and tag. `0.23.2` is the stable identity the next GA
tag (`v0.23.2`) will carry unchanged — the release candidate and the GA cut
share this exact tree and differ only by the added release-notes file, so this
guide stays accurate across that transition without an edit.
Comment on lines +181 to +184

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make the guide remain true after GA

When this exact tree is promoted to v0.23.2, the added phrase “the next GA tag” becomes false while the guide still directs exact-stable users to v0.23.1 at lines 85-103 and shows that version at line 173. Because the GA tree may add only release notes, those instructions cannot be corrected during the cut. Fresh evidence after the prior review is this final added wording and the unchanged v0.23.1 installation section, so the attempted fix does not actually make the guide GA-safe.

AGENTS.md reference: AGENTS.md:L159-L161

Useful? React with 👍 / 👎.


For source checkouts, `lcm_status`, `/lcm status`, `lcm_inspect`,
`lcm_doctor`, and `/lcm doctor` also report the loaded plugin path and
Expand Down
2 changes: 1 addition & 1 deletion plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: hermes-lcm
version: 0.23.0-rc1
version: 0.23.2
description: "LCM-X — Lossless Context Memory eXtension for Hermes, with a recoverable DAG-based context engine"
author: "Voltropy / Hermes Community"
provides_tools:
Expand Down
4 changes: 2 additions & 2 deletions tests/test_lcm_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ def test_lcm_status_reports_runtime_identity(engine):
repo_root = Path(__file__).resolve().parent.parent

assert "plugin_name: hermes-lcm" in result
assert "plugin_version: 0.23.0-rc1" in result
assert "plugin_version: 0.23.2" in result
assert f"plugin_path: {repo_root}" in result
assert "module_path:" in result
assert "database_path_source: config.database_path" in result
Expand Down Expand Up @@ -530,7 +530,7 @@ def test_lcm_doctor_reports_health_checks(engine):
assert "messages_fts: ok" in result
assert "nodes_fts: ok" in result
assert "plugin_name: hermes-lcm" in result
assert "plugin_version: 0.23.0-rc1" in result
assert "plugin_version: 0.23.2" in result
assert f"plugin_path: {repo_root}" in result
assert "plugin_git_commit:" in result
assert "triage_guidance:\n- none" in result
Expand Down
10 changes: 5 additions & 5 deletions tests/test_lcm_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -1345,7 +1345,7 @@ def test_get_status_exposes_runtime_identity_for_loaded_plugin_tree(tmp_path):

assert identity["engine"] == "lcm"
assert identity["plugin_name"] == "hermes-lcm"
assert identity["plugin_version"] == "0.23.0-rc1"
assert identity["plugin_version"] == "0.23.2"
assert Path(identity["plugin_path"]) == repo_root
assert Path(identity["module_path"]).name == "engine.py"
assert Path(identity["database_path"]) == db_path
Expand All @@ -1371,11 +1371,11 @@ def test_plugin_metadata_refreshes_when_manifest_changes(tmp_path, monkeypatch):

initial = identity_mod._plugin_metadata()
assert initial["name"] == "hermes-lcm"
assert initial["version"] == "0.23.0-rc1"
assert initial["version"] == "0.23.2"

updated = original.replace('version: "0.23.0-rc1"', 'version: "9.9.9-test"')
updated = original.replace('version: "0.23.2"', 'version: "9.9.9-test"')
if updated == original:
updated = original.replace('version: 0.23.0-rc1', 'version: 9.9.9-test')
updated = original.replace('version: 0.23.2', 'version: 9.9.9-test')
assert updated != original

try:
Expand Down Expand Up @@ -1413,7 +1413,7 @@ def test_lcm_doctor_json_includes_runtime_identity(engine):
payload = json.loads(engine.handle_tool_call("lcm_doctor", {}))

assert payload["runtime_identity"]["plugin_name"] == "hermes-lcm"
assert payload["runtime_identity"]["plugin_version"] == "0.23.0-rc1"
assert payload["runtime_identity"]["plugin_version"] == "0.23.2"
assert "plugin_git_commit" in payload["runtime_identity"]


Expand Down
2 changes: 1 addition & 1 deletion tests/test_packaging_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ def test_plugin_entrypoint_registers_lcm_context_engine(_isolate_plugin_registra
identity = engine.get_status()["runtime_identity"]
repo_root = Path(__file__).resolve().parent.parent
assert identity["plugin_name"] == "hermes-lcm"
assert identity["plugin_version"] == "0.23.0-rc1"
assert identity["plugin_version"] == "0.23.2"
assert Path(identity["plugin_path"]) == repo_root
assert identity["database_path_source"] == "hermes_home"
assert Path(identity["database_path"]) == _isolate_plugin_registration_storage / "lcm.db"
Expand Down
51 changes: 35 additions & 16 deletions tests/test_release_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

REPO_ROOT = Path(__file__).resolve().parent.parent
RELEASE_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "release.yml"
RELEASE_VERSION = "0.23.0-rc1"
RELEASE_NOTES = REPO_ROOT / ".github" / "release-notes" / f"v{RELEASE_VERSION}.md"
IDENTITY_VERSION = "0.23.2"
RC_TAG = "0.23.2-rc1"
Comment thread
100yenadmin marked this conversation as resolved.
Resolved
RELEASE_NOTES = REPO_ROOT / ".github" / "release-notes" / f"v{RC_TAG}.md"


def test_release_workflow_requires_curated_tag_specific_notes():
Expand Down Expand Up @@ -35,11 +36,27 @@ def test_release_candidate_identity_surfaces_are_synchronized():
REPO_ROOT / ".github" / "ISSUE_TEMPLATE" / "bug_report.yml"
).read_text(encoding="utf-8")

assert f"version: {RELEASE_VERSION}" in manifest
assert f"hermes-lcm v{RELEASE_VERSION} (15 tools)" in readme
assert f"hermes-lcm v{RELEASE_VERSION} (15 tools)" in operator_guide
assert f"## v{RELEASE_VERSION} - " in changelog
assert f"Exact commit SHA for v{RELEASE_VERSION} or main" in bug_report
assert f"version: {IDENTITY_VERSION}" in manifest
assert f"hermes-lcm v{IDENTITY_VERSION} (15 tools)" in readme
assert f"hermes-lcm v{IDENTITY_VERSION} (15 tools)" in operator_guide
assert f"## v{IDENTITY_VERSION} - " in changelog
assert f"Exact commit SHA for v{IDENTITY_VERSION} or main" in bug_report


def test_plugin_version_is_not_a_release_downgrade():
import re

manifest = (REPO_ROOT / "plugin.yaml").read_text(encoding="utf-8")
match = re.search(r"^version:\s*(\S+)", manifest, re.MULTILINE)
assert match is not None, "plugin.yaml declares no version"
declared = match.group(1)
# Parse the release core (drop any -rcN suffix) and assert it never regresses
# below the last shipped stable — a restored older RC (e.g. 0.23.0-rc1) fails
# this even if IDENTITY_VERSION were changed with it (not tautological).
core = tuple(int(part) for part in declared.split("-")[0].split("."))
assert core >= (0, 23, 1), f"plugin.yaml version {declared!r} is a downgrade below the 0.23.1 stable floor"
# And it must match the identity every other surface is synchronized to.
assert declared == IDENTITY_VERSION

Comment thread
100yenadmin marked this conversation as resolved.
Resolved

def test_issue_forms_stay_within_github_element_limit():
Expand Down Expand Up @@ -80,12 +97,14 @@ def test_preanswer_guide_discloses_inherited_embedding_provider_behavior():

def test_release_candidate_notes_cover_only_the_merged_release_scope():
notes = RELEASE_NOTES.read_text(encoding="utf-8")

assert notes.startswith(f"# hermes-lcm v{RELEASE_VERSION}\n")
assert "#177" in notes
assert "## Highlights" in notes
assert "## Changes" in notes
assert "## Contributors" in notes
assert "occurrence-bounded" in notes
assert "DORMANT" in notes
assert len(notes.splitlines()) <= 60
lines = notes.splitlines()
section_headers = [line for line in lines if line.startswith("## ")]

assert notes.startswith(f"# v{RC_TAG} — ")
assert any(header.startswith("## Lossless by default:") for header in section_headers)
assert any(header.startswith("## Security:") for header in section_headers)
assert any(header.startswith("## Instrument integrity:") for header in section_headers)
assert any(header.startswith("## Release process:") for header in section_headers)
assert any(header.startswith("## Known follow-ups") for header in section_headers)
assert "## Benchmark boundary" in section_headers
assert 60 <= len(lines) <= 100
Loading