Skip to content

Commit d2bf3e5

Browse files
feat: consolidate governed recall and release hardening (#108)
* feat: consolidate governed recall and release hardening * fix: isolate conflicting sqlite native backends * test: approve encrypted recall fixture * On codex/v2-trust-boundary-release: transfer primary readiness changes to PR 108 * test: align ingress approval boundary * fix: enforce governed prompt boundaries * chore: harden LAN release packaging * docs: keep post-release notes unreleased * fix: preserve governed graph and claim boundaries * fix: close governed review gaps * fix: enforce eligibility before bounded public scans * fix: remove build-only pip from runtime image * docs: streamline README detail * fix: audit stripped production image * fix: address remaining PR review findings * fix: harden memory retirement and offline recall * fix: audit stripped release image * test: expect retirement control in ledger smoke * feat: harden smart MCP gateway and Pi integration * fix: reject all MCP server error envelopes * docs: restore Pro conversion callout * docs: make full install the default * docs: move Compose details out of README * docs: restore 1.3 README intro * docs: move LAN setup out of README * docs: preserve support badge * docs: move vector backend detail out of README * docs: move public review guidance out of README * docs: move query planning details out of README * fix: address review regressions and core test floor * fix: filter prompt graph edges before frontier cap * fix: preserve review and prompt graph boundaries * fix: honor type caps and MCP restarts
1 parent 4a0a189 commit d2bf3e5

192 files changed

Lines changed: 17672 additions & 1396 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"name": "engraphis-memory",
1010
"source": "./",
1111
"description": "Discipline for giving agents durable, scoped, explainable memory across sessions and repos with the Engraphis MCP tools.",
12-
"version": "1.3.0"
12+
"version": "1.4.0"
1313
}
1414
]
1515
}

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "engraphis-memory",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"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.",
55
"author": {
66
"name": "The Engraphis Authors",

.claude-plugin/skill-assets.sha256

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
24cc8bbcd2ba6055df75178c710542fb6e3e6428e63952ba51cc17d3d6d41a07 .claude-plugin/marketplace.json
2-
6099aa7f5268a34bf1633c1f50c5e59f419b9dcc54ac5d553007fa40f28258ac .claude-plugin/plugin.json
3-
018364f63e2181d83ba8d9532c50a41bd30e65eaa8358a721538c297dd063084 skills/engraphis-memory/SKILL.md
4-
7ee71fb5ff9bd2b02f50b3ee8dc62f390a0e1bcd849a55739c4a376ac03d9784 skills/engraphis-memory/references/CONVENTIONS.md
5-
8aafd2daba872be38ec8d42377e886d795d8941bf7c6a39795937ffc1d1f0d88 skills/engraphis-memory/references/SCOPING.md
6-
6b0bbb97db4bfa4b1682f9f195bd823f05a2950384ea5c5b261b446b9461d1f1 skills/engraphis-memory/references/TOOLS.md
1+
b3122186525b688060558721dadf8ca4a20e192097556adb1daecca0649a4e28 .claude-plugin/marketplace.json
2+
5a870fabc9814e177a570a8878371d1c4c50a5b245076c2cfbb7ca659e41ebf6 .claude-plugin/plugin.json
3+
911c70ead2c5aa3de24a6c645a9e921382a149aba52b0a9582ecd5b560e5b8a8 skills/engraphis-memory/SKILL.md
4+
45dd73ca6afdd9e12ecd38c48e4a612b7646c25a07a75a80ca0e68d0e0b85f0e skills/engraphis-memory/references/CONVENTIONS.md
5+
529fff3bdbe73f83209087fd10055fad77c5e5224ad8a9e6b0254052aa50e109 skills/engraphis-memory/references/SCOPING.md
6+
eecd861f0f8cc2a9def07a53387ca66d8cb68d8b62d9b048dcd1b0b250fa3fee skills/engraphis-memory/references/TOOLS.md

.env.example

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ ENGRAPHIS_SERVICE_MODE=customer
1313
# Set ENGRAPHIS_DASHBOARD_URL for a canonical public HTTPS URL behind a reverse proxy;
1414
# it extends the dashboard MCP origin allow-list and drives legacy-inspector redirects.
1515
# ENGRAPHIS_DASHBOARD_URL=https://engraphis.example.com
16+
# Docker Compose stays loopback-only by default. For LAN MCP-over-HTTP, set a strong
17+
# ENGRAPHIS_API_TOKEN, then run the token-required `docker-compose.lan.yml` overlay (Docker
18+
# Compose v2.24.4+). Set this to the exact client URL:
19+
# ENGRAPHIS_API_TOKEN=<a-long-random-secret>
20+
# ENGRAPHIS_DASHBOARD_URL=http://192.168.10.151:8700
21+
# Behind Traefik, use its LAN hostname instead:
22+
# ENGRAPHIS_DASHBOARD_URL=http://engraphis.local
1623

1724
# Update reminder. When on (default), the server checks for a newer Engraphis release
1825
# once a day and surfaces it in the dashboard banner, the startup log, and over MCP.
@@ -207,17 +214,19 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
207214
# Locally defaults to ~/.engraphis; in a container use a private persistent volume.
208215
# ENGRAPHIS_STATE_DIR=/data/.engraphis
209216

210-
# Hosted entitlements may report a separate local-only write grace capped at 24 hours.
211-
# It never extends the exact 3-day trial, subscription expiry, or any cloud access.
217+
# The private control plane may report ``workspace_write_grace`` for already-authorized
218+
# hosted-account continuity, capped at 24 hours. It never extends the exact 3-day trial,
219+
# subscription expiry, or cloud access, and it never restricts the free local core.
212220

213221
# Managed compute consent is decided automatically and needs no customer action: a
214222
# local-only installation (no cloud session) is never allowed to upload workspace
215223
# snapshots, while an installation connected to Engraphis Cloud is allowed by default,
216224
# because connecting already accepts the terms covering managed analytics, dreaming, and
217225
# consolidation. This variable is an explicit operator override, not a customer-facing
218-
# setting: set it to 0 to opt a connected installation back out, or to 1 to force
219-
# managed compute on regardless of session state. The cloud service remains authoritative
220-
# for all paid computation.
226+
# setting: set it to 0 to opt a connected installation back out, or to 1 to allow local
227+
# snapshot preparation for a non-interactive deployment. ``1`` does not establish a cloud
228+
# credential or authorize an upload; the cloud service remains authoritative for all paid
229+
# computation.
221230
# ENGRAPHIS_MANAGED_COMPUTE_CONSENT=0
222231

223232
# Optional credential-redacted JSON logs for hosted customer deployments.
@@ -256,18 +265,18 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
256265
# directories allowed as import sources.
257266
# ENGRAPHIS_IMPORT_ROOTS=/srv/docs:/home/user/notes
258267

259-
# Memory engine tuning: decay halflife (days), chunk sizing (tokens),
260-
# proactive context loop, and reranker model.
261-
# ENGRAPHIS_DECAY_HALFLIFE_DAYS=30
262-
# ENGRAPHIS_CHUNK_TOKENS=512
263-
# ENGRAPHIS_CHUNK_MAX=2048
264-
# ENGRAPHIS_CHUNK_OVERLAP=64
268+
# Memory engine tuning: runtime defaults for decay, chunk sizing, and the
269+
# proactive context loop. CHUNK_MAX is a chunk-count limit, not a token limit.
270+
# ENGRAPHIS_DECAY_HALFLIFE_DAYS=7
271+
# ENGRAPHIS_CHUNK_TOKENS=256
272+
# ENGRAPHIS_CHUNK_MAX=200
273+
# ENGRAPHIS_CHUNK_OVERLAP=32
265274
# Optional reader-tokenizer parity for chunk sizes (requires transformers).
266275
# Pin the revision when the resulting memories support reproducible evidence.
267276
# ENGRAPHIS_CHUNK_TOKENIZER_MODEL=Qwen/Qwen3.5-9B
268277
# ENGRAPHIS_CHUNK_TOKENIZER_REVISION=<immutable model commit>
269-
# ENGRAPHIS_LOOP_INTERVAL=300
270-
# ENGRAPHIS_LOOP_TOP_K=10
278+
# ENGRAPHIS_LOOP_INTERVAL=60
279+
# ENGRAPHIS_LOOP_TOP_K=20
271280
# ENGRAPHIS_RERANK_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
272281

273282
# Workspace allow-list: comma-separated names. Empty = all allowed.

.github/workflows/ci.yml

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
2222
with:
2323
python-version: ${{ matrix.python-version }}
24-
- name: Install (core + server/mcp/code extras; no torch — the offline gate)
24+
- name: Install (core + server/mcp/code extras; no torch or SQLCipher)
2525
run: |
2626
python -m pip install --upgrade pip
2727
pip install -e ".[test]"
@@ -42,6 +42,28 @@ jobs:
4242
- name: Ablation (vector-only vs hybrid)
4343
run: python -m eval.ablation
4444

45+
encryption:
46+
name: encryption driver gate (Python ${{ matrix.python-version }})
47+
runs-on: ubuntu-latest
48+
strategy:
49+
fail-fast: false
50+
matrix:
51+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
52+
steps:
53+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
54+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
55+
with:
56+
python-version: ${{ matrix.python-version }}
57+
- name: Install encryption integration gate
58+
run: |
59+
python -m pip install --upgrade pip
60+
pip install -e ".[test,encryption]"
61+
# sqlcipher3-binary currently cannot coexist safely with the stdlib sqlite
62+
# extension during the long general suite. Keep its real driver contract in
63+
# this dedicated, short-lived process rather than skipping encryption coverage.
64+
- name: Encryption at-rest integration tests
65+
run: python -m pytest -o addopts="" tests/test_encrypted_store.py -q -rs
66+
4567
core-py39:
4668
name: core floor (numpy-only, Python 3.9)
4769
runs-on: ubuntu-latest
@@ -61,6 +83,43 @@ jobs:
6183
- name: Ablation
6284
run: python -m eval.ablation
6385

86+
pi-extension:
87+
name: Pi extension (${{ matrix.os }}, Python ${{ matrix.python-version }}, Node ${{ matrix.node-version }})
88+
runs-on: ${{ matrix.os }}
89+
strategy:
90+
fail-fast: false
91+
matrix:
92+
include:
93+
- os: ubuntu-latest
94+
python-version: "3.10"
95+
node-version: "22.19.0"
96+
- os: windows-latest
97+
python-version: "3.11"
98+
node-version: "24"
99+
steps:
100+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
101+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
102+
with:
103+
python-version: ${{ matrix.python-version }}
104+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
105+
with:
106+
node-version: ${{ matrix.node-version }}
107+
cache: npm
108+
cache-dependency-path: integrations/pi/npm-shrinkwrap.json
109+
- name: Install the current Smart MCP server
110+
run: |
111+
python -m pip install --upgrade pip
112+
python -m pip install -e ".[test]"
113+
- name: Install and verify the Pi package
114+
working-directory: integrations/pi
115+
env:
116+
ENGRAPHIS_PI_TEST_COMMAND: engraphis-mcp
117+
run: |
118+
npm ci --ignore-scripts
119+
npm run verify
120+
npm run test:integration
121+
npm audit --omit=dev
122+
64123
browser-accessibility:
65124
name: browser accessibility smoke
66125
runs-on: ubuntu-latest
@@ -98,7 +157,7 @@ jobs:
98157
if [ "${{ github.event_name }}" != "pull_request" ]; then
99158
echo "run=true" >> "$GITHUB_OUTPUT"
100159
elif git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}" \
101-
| grep -qE '^(Dockerfile|docker-entrypoint\.sh|docker-compose\.yml|railway\.json|deploy/|\.dockerignore|engraphis/|scripts/|pyproject\.toml|\.github/workflows/ci\.yml)'; then
160+
| grep -qE '^(Dockerfile|docker-entrypoint\.sh|docker-compose(\.lan)?\.yml|railway\.json|deploy/|\.dockerignore|engraphis/|scripts/|pyproject\.toml|\.github/workflows/ci\.yml)'; then
102161
echo "run=true" >> "$GITHUB_OUTPUT"
103162
else
104163
echo "run=false" >> "$GITHUB_OUTPUT"
@@ -111,6 +170,18 @@ jobs:
111170
if: needs.docker-gate.outputs.run == 'true'
112171
steps:
113172
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
173+
- name: Validate Compose configuration
174+
run: docker compose config --quiet
175+
- name: Reject unauthenticated LAN Compose overlay
176+
run: |
177+
if env -u ENGRAPHIS_API_TOKEN docker compose -f docker-compose.yml -f docker-compose.lan.yml config --quiet; then
178+
echo "LAN overlay must require ENGRAPHIS_API_TOKEN"
179+
exit 1
180+
fi
181+
- name: Validate token-protected LAN Compose overlay
182+
env:
183+
ENGRAPHIS_API_TOKEN: ci-lan-overlay-token
184+
run: docker compose -f docker-compose.yml -f docker-compose.lan.yml config --quiet
114185
- name: Build image
115186
run: docker build -t engraphis:ci .
116187
- name: Verify production image OCR runtime
@@ -119,10 +190,22 @@ jobs:
119190
'python -c "import PIL, pytesseract" && command -v tesseract >/dev/null &&
120191
tesseract --version | head -n 1'
121192
- name: Audit the exact production image dependency set
122-
run: >-
123-
docker run --rm --entrypoint sh engraphis:ci -c
124-
'python -m pip install --no-cache-dir pip-audit &&
125-
python -m pip_audit --local'
193+
# The runtime image intentionally has no pip: it is a build tool whose vendored
194+
# dependency snapshot would otherwise remain an unnecessary attack surface. Copy the
195+
# exact installed distributions to the runner and audit that set instead of mutating
196+
# the production image just to run the audit.
197+
run: |
198+
audit_dir="$(mktemp -d)"
199+
container="engraphis-audit-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
200+
cleanup() {
201+
docker rm -f "$container" >/dev/null 2>&1 || true
202+
rm -rf "$audit_dir"
203+
}
204+
trap cleanup EXIT
205+
python -m pip install --disable-pip-version-check --no-cache-dir pip-audit
206+
docker create --name "$container" engraphis:ci >/dev/null
207+
docker cp "$container":/usr/local/lib/python3.11/site-packages/. "$audit_dir"
208+
python -m pip_audit --path "$audit_dir"
126209
- name: Run container (offline deterministic embedder — no model downloads)
127210
run: |
128211
docker run -d --name engraphis -p 8700:8700 \

.github/workflows/release-pi.yml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: Publish Pi extension to npm
2+
3+
on:
4+
push:
5+
tags:
6+
- "pi-v*.*.*"
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
build:
14+
name: Verify and pack Pi extension
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
18+
with:
19+
fetch-depth: 0
20+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
21+
with:
22+
python-version: "3.11"
23+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
24+
with:
25+
node-version: "24"
26+
cache: npm
27+
cache-dependency-path: integrations/pi/npm-shrinkwrap.json
28+
registry-url: https://registry.npmjs.org
29+
30+
- name: Require Pi tag and npm package version to match
31+
if: github.event_name == 'push'
32+
shell: bash
33+
run: |
34+
expected="${GITHUB_REF_NAME#pi-v}"
35+
actual="$(node -p 'require("./integrations/pi/package.json").version')"
36+
test "$GITHUB_REF_NAME" = "pi-v$actual"
37+
test "$expected" = "$actual"
38+
39+
- name: Require release tag commit to be on protected main
40+
if: github.event_name == 'push'
41+
shell: bash
42+
run: |
43+
git fetch --no-tags origin main:refs/remotes/origin/main
44+
git merge-base --is-ancestor "$GITHUB_SHA" origin/main
45+
46+
- name: Install the current Smart MCP server
47+
run: |
48+
python -m pip install --upgrade pip
49+
python -m pip install -e ".[test]"
50+
51+
- name: Verify package, live MCP bridge, and production dependencies
52+
working-directory: integrations/pi
53+
env:
54+
ENGRAPHIS_PI_TEST_COMMAND: engraphis-mcp
55+
run: |
56+
npm ci --ignore-scripts
57+
npm run verify
58+
npm run test:integration
59+
npm audit --omit=dev
60+
61+
- name: Build npm tarball
62+
working-directory: integrations/pi
63+
run: npm pack --ignore-scripts
64+
65+
- name: Store npm tarball
66+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
67+
with:
68+
name: pi-npm-package
69+
path: integrations/pi/engraphis-pi-*.tgz
70+
if-no-files-found: error
71+
72+
publish:
73+
name: Publish @engraphis/pi
74+
needs: build
75+
# A manual dispatch is intentionally verification-only. Publishing requires a
76+
# protected pi-v* tag and npm Trusted Publishing configured for this workflow.
77+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/pi-v')
78+
runs-on: ubuntu-latest
79+
permissions:
80+
contents: read
81+
id-token: write
82+
steps:
83+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
84+
with:
85+
node-version: "24"
86+
registry-url: https://registry.npmjs.org
87+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
88+
with:
89+
name: pi-npm-package
90+
path: dist
91+
- name: Publish with npm provenance
92+
run: npm publish dist/engraphis-pi-*.tgz --access public --provenance
93+
- name: Verify the published version
94+
shell: bash
95+
run: |
96+
version="${GITHUB_REF_NAME#pi-v}"
97+
for attempt in $(seq 1 12); do
98+
if [ "$(npm view "@engraphis/pi@$version" version 2>/dev/null)" = "$version" ]; then
99+
exit 0
100+
fi
101+
sleep 10
102+
done
103+
echo "@engraphis/pi@$version did not become visible on npm"
104+
exit 1

0 commit comments

Comments
 (0)