Skip to content
Closed
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 .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"name": "engraphis-memory",
"source": "./",
"description": "Discipline for giving agents durable, scoped, explainable memory across sessions and repos with the Engraphis MCP tools.",
"version": "1.5.0"
"version": "1.5"
}
]
}
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "engraphis-memory",
"version": "1.5.0",
"version": "1.5",
"description": "Give agents durable, scoped, explainable memory across sessions and repos via the Engraphis MCP tools. Use when you learn something worth keeping, need prior context before acting, or ask why/how a fact changed. Covers remember/recall, why/timeline, forget/pin/correct, sessions, and code search.",
"author": {
"name": "The Engraphis Authors",
Expand Down
6 changes: 3 additions & 3 deletions .claude-plugin/skill-assets.sha256
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
5d315146fd0bdcd5bb803bab482504c51e6c8e94d9666cd4910ca8f4a645b564 .claude-plugin/marketplace.json
a51eb5baab17efb66193759be7f68df32451594b799476e7ec6e3b076b7fdff5 .claude-plugin/plugin.json
56be8d078a2a8fc6e6cd1c2be5716605d8621dab953caa8cfcd20e2dce474305 skills/engraphis-memory/SKILL.md
d30ad152dcc4c82ce10e7167fdfe67e709358e5f435293939125f2d6cffc5b7e .claude-plugin/marketplace.json
28dcd15a7a186f8cb8a15705f1bd7734086167991c4acc28ec2cfea59a2374ab .claude-plugin/plugin.json
45dd73ca6afdd9e12ecd38c48e4a612b7646c25a07a75a80ca0e68d0e0b85f0e skills/engraphis-memory/references/CONVENTIONS.md
529fff3bdbe73f83209087fd10055fad77c5e5224ad8a9e6b0254052aa50e109 skills/engraphis-memory/references/SCOPING.md
b2489b60159655e7e564e234d5aff24ba4d8df7cb82626edeaaaf89264007f85 skills/engraphis-memory/references/TOOLS.md
56be8d078a2a8fc6e6cd1c2be5716605d8621dab953caa8cfcd20e2dce474305 skills/engraphis-memory/SKILL.md
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to Engraphis are documented here. Format loosely follows

## [Unreleased]

## [1.5.0] - 2026-08-04
## [1.5] - 2026-08-04

Minor release advancing the v2 engine to schema 11 with governed recall recovery,
embedding-space safety, reproducible release evidence, and stronger offline memory-quality gates.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ selection, set `ENGRAPHIS_UPDATE_EXTRAS` to a comma-separated list (for example
> **Upgrading to 1.5:** schema 10 bounds legacy retention state and schema 11 backfills explicit
> approval only for eligible pre-review local memories. Pending and quarantined evidence remains
> gated. Existing 1.4.x databases migrate automatically when Engraphis 1.5 opens them; see the
> [1.5.0 release notes](CHANGELOG.md#150---2026-08-04).
> [1.5 release notes](CHANGELOG.md#150---2026-08-04).

---

Expand Down
4 changes: 2 additions & 2 deletions engraphis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from importlib.metadata import PackageNotFoundError, version as _dist_version

_SOURCE_VERSION = "1.5.0"
_SOURCE_VERSION = "1.5"

try:
__version__ = _dist_version("engraphis")
Expand All @@ -14,4 +14,4 @@
except PackageNotFoundError: # source tree without an installed distribution
# Keep in step with [project] version in pyproject.toml — tests/test_packaging.py
# pins the two together so a release cannot ship them out of sync.
__version__ = "1.5.0"
__version__ = "1.5"
2 changes: 1 addition & 1 deletion engraphis/commercial_manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema": "engraphis-commercial/v2",
"version": "1.5.0",
"version": "1.5",
"control_plane": "https://api.engraphis.com",
"account_portal": "https://api.engraphis.com/account",
"billing": {
Expand Down
326 changes: 163 additions & 163 deletions engraphis/core/savings.py
Original file line number Diff line number Diff line change
@@ -1,163 +1,163 @@
"""Pure token-savings estimation for prompt-context deliveries.

The estimator deliberately distinguishes an actual host-history baseline from the
smaller source-packing baseline used by ordinary recall. It is an estimate of
avoided prompt context, not provider billing or end-to-end task cost.
"""
from __future__ import annotations

import math
import re
from dataclasses import dataclass
from typing import Any, Optional


_RELEASE_VERSION = re.compile(r"^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$")


@dataclass(frozen=True)
class SavingsEstimate:
"""One explainable, content-free token-savings estimate."""

baseline_tokens: int
emitted_tokens: int
saved_tokens: int
savings_ratio: float
basis: str
confidence: str
eligible: bool
token_counter: str = "unknown"
release_version: Optional[str] = None

@property
def estimated_saved_tokens(self) -> int:
"""Name used by receipt metadata for the same saved-token value."""
return self.saved_tokens

def to_dict(self) -> dict[str, Any]:
return {
"baseline_tokens": self.baseline_tokens,
"emitted_tokens": self.emitted_tokens,
"saved_tokens": self.saved_tokens,
"savings_ratio": self.savings_ratio,
"basis": self.basis,
"confidence": self.confidence,
"eligible": self.eligible,
"token_counter": self.token_counter,
**({"release_version": self.release_version}
if self.release_version else {}),
}


def normalize_release_version(value: Any) -> Optional[str]:
"""Return a safe release label, or ``None`` for historical/unversioned data."""
if not isinstance(value, str):
return None
value = value.strip()
return value if _RELEASE_VERSION.fullmatch(value) else None


def _count(value: Any) -> int:
if type(value) not in (int, float):
return 0
if not math.isfinite(float(value)) or value < 0:
return 0
return int(value)


def estimate_savings(
*,
operation: str,
baseline_tokens: Any,
emitted_tokens: Any,
token_counter: str = "unknown",
intent: Optional[str] = None,
adaptive_mode: Optional[str] = None,
release_version: Optional[str] = None,
) -> SavingsEstimate:
"""Classify one delivery and compute its conservative savings estimate.

``adaptive_context`` has a real before/after history baseline. The packed
context operations use their retrieved-source total as a narrower packing
baseline. Ordinary full recall is not counted because callers may not inject
its returned memories into a model prompt.
"""
operation = str(operation or "").strip().casefold()
intent = str(intent or "").strip().casefold()
mode = str(adaptive_mode or "").strip().casefold()

basis = "unclassified"
confidence = "unknown"
eligible = False

if operation == "adaptive_context":
if mode == "retrieval":
basis, confidence, eligible = "history_retrieval", "high", True
elif mode == "history_fallback":
basis, confidence, eligible = "history_fallback", "medium", True
elif mode == "history_bypass":
basis, confidence, eligible = "history_bypass", "none", False
elif mode == "low_confidence_abstain":
basis, confidence, eligible = "low_confidence_abstain", "none", False
elif operation == "recall" and intent == "recall_context":
basis, confidence, eligible = "packed_context", "medium", True
elif operation in {"grounded_recall", "proactive_context"}:
basis, confidence, eligible = "packed_context", "medium", True

baseline = _count(baseline_tokens)
emitted = _count(emitted_tokens)
saved = max(0, baseline - emitted) if eligible else 0
ratio = saved / baseline if baseline else 0.0
counter = str(token_counter or "unknown")
return SavingsEstimate(
baseline_tokens=baseline,
emitted_tokens=emitted,
saved_tokens=saved,
savings_ratio=ratio,
basis=basis,
confidence=confidence,
eligible=eligible,
token_counter=counter,
release_version=normalize_release_version(release_version),
)


def annotate_usage(
usage: dict[str, Any],
*,
operation: str,
intent: Optional[str] = None,
adaptive_mode: Optional[str] = None,
baseline_tokens: Any = None,
emitted_tokens: Any = None,
release_version: Optional[str] = None,
) -> dict[str, Any]:
"""Add estimator fields to an existing public usage dictionary."""
estimate = estimate_savings(
operation=operation,
intent=intent,
adaptive_mode=adaptive_mode,
baseline_tokens=(
usage.get("source_tokens", 0)
if baseline_tokens is None else baseline_tokens
),
emitted_tokens=(
usage.get("context_tokens", 0)
if emitted_tokens is None else emitted_tokens
),
token_counter=str(usage.get("token_counter") or "unknown"),
release_version=release_version,
)
out = dict(usage)
out.update({
"baseline_tokens": estimate.baseline_tokens,
"emitted_tokens": estimate.emitted_tokens,
"estimated_saved_tokens": estimate.saved_tokens,
"estimated_savings_ratio": estimate.savings_ratio,
"savings_basis": estimate.basis,
"savings_confidence": estimate.confidence,
"savings_eligible": estimate.eligible,
})
if estimate.release_version:
out["release_version"] = estimate.release_version
return out
"""Pure token-savings estimation for prompt-context deliveries.
The estimator deliberately distinguishes an actual host-history baseline from the
smaller source-packing baseline used by ordinary recall. It is an estimate of
avoided prompt context, not provider billing or end-to-end task cost.
"""
from __future__ import annotations
import math
import re
from dataclasses import dataclass
from typing import Any, Optional
_RELEASE_VERSION = re.compile(r"^\d+\.\d+(?:\.\d+)?(?:[-+][0-9A-Za-z.-]+)?$")
@dataclass(frozen=True)
class SavingsEstimate:
"""One explainable, content-free token-savings estimate."""
baseline_tokens: int
emitted_tokens: int
saved_tokens: int
savings_ratio: float
basis: str
confidence: str
eligible: bool
token_counter: str = "unknown"
release_version: Optional[str] = None
@property
def estimated_saved_tokens(self) -> int:
"""Name used by receipt metadata for the same saved-token value."""
return self.saved_tokens
def to_dict(self) -> dict[str, Any]:
return {
"baseline_tokens": self.baseline_tokens,
"emitted_tokens": self.emitted_tokens,
"saved_tokens": self.saved_tokens,
"savings_ratio": self.savings_ratio,
"basis": self.basis,
"confidence": self.confidence,
"eligible": self.eligible,
"token_counter": self.token_counter,
**({"release_version": self.release_version}
if self.release_version else {}),
}
def normalize_release_version(value: Any) -> Optional[str]:
"""Return a safe release label, or ``None`` for historical/unversioned data."""
if not isinstance(value, str):
return None
value = value.strip()
return value if _RELEASE_VERSION.fullmatch(value) else None
def _count(value: Any) -> int:
if type(value) not in (int, float):
return 0
if not math.isfinite(float(value)) or value < 0:
return 0
return int(value)
def estimate_savings(
*,
operation: str,
baseline_tokens: Any,
emitted_tokens: Any,
token_counter: str = "unknown",
intent: Optional[str] = None,
adaptive_mode: Optional[str] = None,
release_version: Optional[str] = None,
) -> SavingsEstimate:
"""Classify one delivery and compute its conservative savings estimate.
``adaptive_context`` has a real before/after history baseline. The packed
context operations use their retrieved-source total as a narrower packing
baseline. Ordinary full recall is not counted because callers may not inject
its returned memories into a model prompt.
"""
operation = str(operation or "").strip().casefold()
intent = str(intent or "").strip().casefold()
mode = str(adaptive_mode or "").strip().casefold()
basis = "unclassified"
confidence = "unknown"
eligible = False
if operation == "adaptive_context":
if mode == "retrieval":
basis, confidence, eligible = "history_retrieval", "high", True
elif mode == "history_fallback":
basis, confidence, eligible = "history_fallback", "medium", True
elif mode == "history_bypass":
basis, confidence, eligible = "history_bypass", "none", False
elif mode == "low_confidence_abstain":
basis, confidence, eligible = "low_confidence_abstain", "none", False
elif operation == "recall" and intent == "recall_context":
basis, confidence, eligible = "packed_context", "medium", True
elif operation in {"grounded_recall", "proactive_context"}:
basis, confidence, eligible = "packed_context", "medium", True
baseline = _count(baseline_tokens)
emitted = _count(emitted_tokens)
saved = max(0, baseline - emitted) if eligible else 0
ratio = saved / baseline if baseline else 0.0
counter = str(token_counter or "unknown")
return SavingsEstimate(
baseline_tokens=baseline,
emitted_tokens=emitted,
saved_tokens=saved,
savings_ratio=ratio,
basis=basis,
confidence=confidence,
eligible=eligible,
token_counter=counter,
release_version=normalize_release_version(release_version),
)
def annotate_usage(
usage: dict[str, Any],
*,
operation: str,
intent: Optional[str] = None,
adaptive_mode: Optional[str] = None,
baseline_tokens: Any = None,
emitted_tokens: Any = None,
release_version: Optional[str] = None,
) -> dict[str, Any]:
"""Add estimator fields to an existing public usage dictionary."""
estimate = estimate_savings(
operation=operation,
intent=intent,
adaptive_mode=adaptive_mode,
baseline_tokens=(
usage.get("source_tokens", 0)
if baseline_tokens is None else baseline_tokens
),
emitted_tokens=(
usage.get("context_tokens", 0)
if emitted_tokens is None else emitted_tokens
),
token_counter=str(usage.get("token_counter") or "unknown"),
release_version=release_version,
)
out = dict(usage)
out.update({
"baseline_tokens": estimate.baseline_tokens,
"emitted_tokens": estimate.emitted_tokens,
"estimated_saved_tokens": estimate.saved_tokens,
"estimated_savings_ratio": estimate.savings_ratio,
"savings_basis": estimate.basis,
"savings_confidence": estimate.confidence,
"savings_eligible": estimate.eligible,
})
if estimate.release_version:
out["release_version"] = estimate.release_version
return out
1 change: 0 additions & 1 deletion glama.json

This file was deleted.

Loading