Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
720e54c
chore: Compose reviewed code-only reliability candidate
buildingjoshbetter Oct 12, 2026
8402d0b
fix: Canonicalize synthetic Hermes fixture paths
buildingjoshbetter Oct 12, 2026
f624aed
fix: Preserve test assertions while satisfying hosted lint
buildingjoshbetter Oct 12, 2026
a66d185
fix: Preserve platform file identities and fixture encodings
buildingjoshbetter Oct 12, 2026
ac3c447
test: Measure Windows default owner and explicit file ownership
buildingjoshbetter Oct 13, 2026
38620d9
feat: Integrate accepted memory accounting and bounded launch controls
buildingjoshbetter Oct 13, 2026
cac7c2b
fix: Preserve inert rebuild policy import boundaries
buildingjoshbetter Oct 13, 2026
07c1066
fix: Keep native test fixtures portable across hosted runners
buildingjoshbetter Oct 13, 2026
12b65f1
fix: Disable unused decoder caches in Qwen embedding models
buildingjoshbetter Oct 13, 2026
40928be
test: Require disabled Qwen decoder caches in constructor options
buildingjoshbetter Oct 13, 2026
ea37b2a
fix: Create Windows ingestion files with private birth ownership
buildingjoshbetter Oct 13, 2026
6fd04f8
test: Isolate POSIX policy fixtures on Windows
buildingjoshbetter Oct 13, 2026
09f99ab
fix: Stop Windows completion directory recursion at a missing drive root
buildingjoshbetter Oct 13, 2026
37342c7
fix: Treat Claude Code session metadata records as non-conversation
buildingjoshbetter Oct 13, 2026
c4f102f
fix: Skip only known Claude context attachments and recorded queued p…
buildingjoshbetter Oct 13, 2026
001e8f1
fix: Count attachments with non-string types as malformed
buildingjoshbetter Oct 13, 2026
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.py text eol=lf
66 changes: 54 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ jobs:
cache-dependency-path: pyproject.toml
- name: Install dependencies
run: pip install -e ".[all,dev]"
- name: Trace synthetic Windows file ownership
if: runner.os == 'Windows'
run: python tests/native/windows-owned-file-diagnostics-v2.py
- name: Run tests (gate — deterministic, no network)
# Issue #426: exclude `network`-marked tests (real HuggingFace model
# downloads) from the gate so a transient HfHubHTTPError can't fail CI
Expand Down Expand Up @@ -115,17 +118,38 @@ jobs:

# Hunter F26: catch packaging regressions (missing py.typed, metadata
# errors, broken README rendering, sdist contents) in CI instead of
# at release time. Runs once on 3.12 only — duplicating across the
# matrix wastes CI minutes without additional signal.
# at release time. Exercise both MCP dependency boundaries on each OS.
build-check:
runs-on: ubuntu-latest
timeout-minutes: 10
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.12"]
mcp-version: [minimum, latest]
pydantic-version: [latest]
include:
- os: ubuntu-latest
python-version: "3.10"
mcp-version: minimum
pydantic-version: latest
# Exercise the MCP/Pydantic floor pair and the release that removed
# eval_type_backport. Other dependencies still use normal resolution.
- os: ubuntu-latest
python-version: "3.10"
mcp-version: minimum
pydantic-version: "2.11.0"
- os: ubuntu-latest
python-version: "3.12"
mcp-version: minimum
pydantic-version: "2.14.0"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Python 3.12
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: pyproject.toml
- name: Install build tooling
Expand All @@ -134,10 +158,28 @@ jobs:
run: python -m build
- name: Verify package metadata
run: twine check --strict dist/*
# Issue #654 (M-83): actually install the built wheel and exercise the
# console entry point, so a broken/missing entry-point or import-time
# failure is caught here (not just at release).
- name: Install wheel and smoke-test console script
# Issue #757: an editable install or --help alone does not exercise
# the installed wheel's MCP handshake and serialized tool metadata.
- name: Install wheel and verify MCP compatibility
shell: python
env:
MCP_VERSION: ${{ matrix.mcp-version }}
PYDANTIC_VERSION: ${{ matrix.pydantic-version }}
run: |
pip install dist/*.whl
truememory-mcp --help
import os
from pathlib import Path
import subprocess
import venv

wheel, = Path("dist").glob("*.whl")
env_dir = Path(os.environ["RUNNER_TEMP"]) / "mcp-wheel-env"
venv.EnvBuilder(with_pip=True).create(env_dir)
python = env_dir / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
requirements = [str(wheel.resolve())]
if os.environ["MCP_VERSION"] == "minimum":
requirements.append("mcp[cli]==1.21.1")
if os.environ["PYDANTIC_VERSION"] != "latest":
requirements.append("pydantic==" + os.environ["PYDANTIC_VERSION"])
subprocess.run([str(python), "-m", "pip", "install", *requirements], check=True)
subprocess.run([str(python), "-m", "pip", "check"], check=True)
subprocess.run([str(python), "-I", "tests/mcp-wheel-smoke.py"], check=True)
35 changes: 34 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ jobs:

build-check:
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
mcp-version: [minimum, latest]
pydantic-version: [latest]
include:
- mcp-version: minimum
pydantic-version: "2.11.0"
- mcp-version: minimum
pydantic-version: "2.14.0"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
Expand All @@ -46,6 +56,29 @@ jobs:
run: python -m build
- name: Verify package metadata
run: twine check --strict dist/*
- name: Install wheel and verify MCP compatibility
shell: python
env:
MCP_VERSION: ${{ matrix.mcp-version }}
PYDANTIC_VERSION: ${{ matrix.pydantic-version }}
run: |
import os
from pathlib import Path
import subprocess
import venv

wheel, = Path("dist").glob("*.whl")
env_dir = Path(os.environ["RUNNER_TEMP"]) / "mcp-wheel-env"
venv.EnvBuilder(with_pip=True).create(env_dir)
python = env_dir / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
requirements = [str(wheel.resolve())]
if os.environ["MCP_VERSION"] == "minimum":
requirements.append("mcp[cli]==1.21.1")
if os.environ["PYDANTIC_VERSION"] != "latest":
requirements.append("pydantic==" + os.environ["PYDANTIC_VERSION"])
subprocess.run([str(python), "-m", "pip", "install", *requirements], check=True)
subprocess.run([str(python), "-m", "pip", "check"], check=True)
subprocess.run([str(python), "-I", "tests/mcp-wheel-smoke.py"], check=True)

version-check:
runs-on: ubuntu-latest
Expand Down
84 changes: 59 additions & 25 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ if ($LASTEXITCODE -ne 0) {
}

# ---------- step 3: install truememory as a uv tool ----------
Say "installing $PKG_SPEC (~3-5 min on first run, downloads all tier models)..."
Say "installing $PKG_SPEC (~3-5 min on first run)..."
& uv tool uninstall truememory *> $null
if ($LASTEXITCODE -gt 1) {
Warn "uv tool uninstall returned $LASTEXITCODE — proceeding, but result may be partial"
Expand Down Expand Up @@ -118,6 +118,8 @@ if ($uvToolDir) {
}

# ---------- step 4: auto-configure Claude ----------
$setupStatus = "skipped"
$hookStatus = "skipped"
if ($env:TRUEMEMORY_SKIP_SETUP -eq "1") {
Say "skipping Claude setup (TRUEMEMORY_SKIP_SETUP=1)"
} elseif (-not $toolPython) {
Expand All @@ -126,41 +128,52 @@ if ($env:TRUEMEMORY_SKIP_SETUP -eq "1") {
} else {
Say "configuring Claude Code / Claude Desktop..."
& $toolPython -m truememory.mcp_server --setup
if ($LASTEXITCODE -ne 0) {
if ($LASTEXITCODE -eq 0) { $setupStatus = "command succeeded" }
else {
$setupStatus = "failed"
Warn "auto-setup returned non-zero (re-run: python -m truememory.mcp_server --setup)"
}

Say "installing hooks and CLAUDE.md instructions..."
& $toolPython -m truememory.ingest.cli install
if ($LASTEXITCODE -ne 0) {
if ($LASTEXITCODE -eq 0) { $hookStatus = "command succeeded" }
else {
$hookStatus = "failed"
Warn "hook install returned non-zero (re-run: python -m truememory.ingest.cli install)"
}
}

# ---------- step 5: pre-download models for all tiers ----------
Say "pre-downloading models for all tiers (Edge + Base + Pro)..."
Say " this takes 2-5 min but means tier switching just works afterward."
if (Test-Path $toolPython) {
Say " [1/3] Edge reranker (MiniLM-L-6-v2, ~22MB)..."
& $toolPython -c "from sentence_transformers import CrossEncoder; CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')"
if ($LASTEXITCODE -eq 0) { Ok " [1/3] Edge reranker ready" }
else { Warn " [1/3] Edge reranker download failed (search still works without it)" }

Say " [2/3] Base/Pro embedder (Qwen3-Embedding-0.6B, ~1.2GB)..."
& $toolPython -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('Qwen/Qwen3-Embedding-0.6B', truncate_dim=256)"
if ($LASTEXITCODE -eq 0) { Ok " [2/3] Base/Pro embedder ready" }
else { Warn " [2/3] Base/Pro embedder download failed (you can retry later or use Edge tier)" }

Say " [3/3] Base/Pro reranker (gte-modernbert, ~600MB)..."
& $toolPython -c "from sentence_transformers import CrossEncoder; CrossEncoder('Alibaba-NLP/gte-reranker-modernbert-base')"
if ($LASTEXITCODE -eq 0) { Ok " [3/3] Base/Pro reranker ready" }
else { Warn " [3/3] Base/Pro reranker download failed (you can retry later or use Edge tier)" }

Ok "all models pre-downloaded — tier switching is instant."
Say "pre-downloading the Edge reranker and Base/Pro models..."
Say " this can take 2-5 min; uncached models require network access."
$modelChecks = @(
@{ Label = "Edge reranker"; Status = "not checked"; Code = "from sentence_transformers import CrossEncoder; CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')" },
@{ Label = "Base/Pro embedder"; Status = "not checked"; Code = "from sentence_transformers import SentenceTransformer; SentenceTransformer('Qwen/Qwen3-Embedding-0.6B', truncate_dim=256)" },
@{ Label = "Base/Pro reranker"; Status = "not checked"; Code = "from sentence_transformers import CrossEncoder; CrossEncoder('Alibaba-NLP/gte-reranker-modernbert-base')" }
)
if ($toolPython -and (Test-Path -LiteralPath $toolPython)) {
foreach ($modelCheck in $modelChecks) {
Say " Pre-downloading $($modelCheck.Label)..."
$modelCheck.Status = "failed"
try {
& $toolPython -c $modelCheck.Code
if ($LASTEXITCODE -eq 0) { $modelCheck.Status = "ready" }
} catch {
Warn " $($modelCheck.Label) could not be loaded: $_"
}
if ($modelCheck.Status -eq "ready") {
Ok " $($modelCheck.Label) ready"
} else {
Warn " $($modelCheck.Label) pre-download failed"
Warn "Retry this model only: & (Join-Path (uv tool dir) 'truememory\Scripts\python.exe') -c `"$($modelCheck.Code)`""
}
}
} else {
Warn "could not locate tool Python at $toolPython — skipping model pre-download"
Warn "models will download on first use instead"
Warn "Model readiness is unverified. Locate the tool environment with: uv tool dir"
Warn "After locating its Python, run: python -m truememory.ingest.cli setup"
}
$modelReadyCount = @($modelChecks | Where-Object { $_.Status -eq "ready" }).Count

# ---------- done ----------
Write-Host ""
Expand All @@ -174,10 +187,31 @@ Write-Host @"
a sauron company
"@ -ForegroundColor Green

$installedVer = & $toolPython -c "from importlib.metadata import version; print(version('truememory'))" 2>$null
$installedVer = $null
if ($toolPython) {
try {
$installedVer = & $toolPython -c "from importlib.metadata import version; print(version('truememory'))" 2>$null
} catch {
$installedVer = $null
}
}
if (-not $installedVer) { $installedVer = "unknown" }
Write-Host ""
Ok "TrueMemory v$installedVer installed successfully."
Ok "TrueMemory v$installedVer package installed."
Say "Claude registration: $setupStatus"
Say "Hooks: $hookStatus"
Say "Model pre-download checks: $modelReadyCount/3 succeeded."
foreach ($modelCheck in $modelChecks) {
Say " $($modelCheck.Label): $($modelCheck.Status)"
}
if ($modelReadyCount -eq 3) {
Ok "All three requested model pre-download checks passed."
} else {
Warn "Model readiness incomplete; package installation is retained. Retry the failed or skipped checks before relying on those models."
}
Say "The Edge embedder was not checked by this pre-download step."
Say "Registration and hook command success do not verify runtime operation."
Say "Changing embedding models can still require re-embedding stored memories."
Write-Host ""
Write-Host " First time? Start a new Claude session and type:" -ForegroundColor Green
Write-Host ""
Expand Down
Loading
Loading