Skip to content

Commit a73b134

Browse files
feat: add adaptive context productivity evaluation (#99)
* feat: add adaptive context productivity evaluation * fix: address adaptive context review findings * feat: harden local memory release surfaces * fix: contain hosted Luna workers on Windows * fix: address adaptive context review findings * fix: harden CodeQL data flows * fix: isolate trust resolution and recall depth * fix: address prompt recall review findings * fix: migrate deterministic embedding vectors * fix: harden hosted evaluation support * docs: clarify product surfaces * fix: preserve ingress trust boundaries * docs: correct release and install guidance * fix: bound prompt-safe review paths * test: cover untrusted structured graph writes * fix: harden review safety paths * fix: mirror rebuilt migration vectors * docs: update unreleased changelog * fix: stage public benchmark claims * fix: cluster hosted evidence bootstrap * docs: complete recent changelog coverage * fix-review-fallback-trust * fix-poisoning-graph-retirement
1 parent cbba2a3 commit a73b134

115 files changed

Lines changed: 12794 additions & 740 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.

.env.example

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ ENGRAPHIS_API_TOKEN=
5353
# A 64-hex value is used as a raw 32-byte key; anything else is treated as a passphrase.
5454
# WARNING: lose this key = lose the data (no recovery). In production, inject it from a
5555
# secrets manager (or ENGRAPHIS_DB_KEY_FILE), NOT from this file. An existing PLAINTEXT
56-
# db cannot just be keyed — migrate it (dump → import into a fresh keyed db).
56+
# db cannot just be keyed. Migrate it (dump → import into a fresh keyed db).
5757
# ENGRAPHIS_DB_KEY=
5858
# ...or read the key from a file (e.g. a mounted docker/k8s secret):
5959
# ENGRAPHIS_DB_KEY_FILE=/run/secrets/engraphis_db_key
@@ -66,6 +66,7 @@ ENGRAPHIS_EMBED_MODEL=sentence-transformers/all-MiniLM-L6-v2
6666

6767
# ── LLM (external, you choose the provider) ─────────────────────────────────
6868
# Provider: openai | anthropic | google | openrouter | custom
69+
# Copy-ready provider setups and endpoint requirements: docs/LLM_PROVIDERS.md
6970
# ── v2 write-path fact extraction (optional) ─────────────────────────────────
7071
# "none" (default): store text as given. "chunk": deterministic offline chunks.
7172
# "llm": free-form fact extraction. "llm_structured": schema-validated typed facts,
@@ -80,7 +81,7 @@ ENGRAPHIS_LLM_AUTO_EXTRACT=0
8081

8182
# ── Knowledge-graph extraction (powers the dashboard Graph tab) ──────────────
8283
# "regex" (default): dependency-free heuristic NER runs on every ingest so the Graph tab
83-
# has nodes no API key, safe offline. "none": disable heuristic text extraction.
84+
# has nodes: no API key, safe offline. "none": disable heuristic text extraction.
8485
# Validated entity/relation metadata from "llm_structured" still feeds the graph
8586
# automatically. Existing memories are backfilled when a workspace graph first opens.
8687
ENGRAPHIS_GRAPH_EXTRACTOR=regex
@@ -122,7 +123,7 @@ ENGRAPHIS_RETENTION_SUPERVISOR=none
122123
# header entirely, which is what you want when a fronting proxy sets its own.
123124
# The default CSP is strict same-origin and contains no unsafe-inline; dashboard CSS,
124125
# JavaScript, and vendored libraries are served under /static.
125-
# Quote the values both contain characters a shell would otherwise split on.
126+
# Quote the values because both contain characters a shell would otherwise split on.
126127
# ENGRAPHIS_CSP="default-src 'self'; frame-ancestors 'none'" # replace the policy
127128
# ENGRAPHIS_CSP="" # send no CSP at all
128129
# ENGRAPHIS_HSTS="max-age=31536000; includeSubDomains"
@@ -140,6 +141,12 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
140141
# For openrouter / custom: the base URL of the OpenAI-compatible endpoint.
141142
# openrouter: https://openrouter.ai/api/v1
142143
# custom: https://your-endpoint/v1
144+
# ollama: http://localhost:11434/v1
145+
# Ollama example (replace the model with one you have pulled):
146+
# ENGRAPHIS_LLM_PROVIDER=custom
147+
# ENGRAPHIS_LLM_MODEL=qwen2.5-coder:latest
148+
# ENGRAPHIS_LLM_API_KEY=ollama # must be non-empty; default local Ollama ignores it
149+
# ENGRAPHIS_LLM_BASE_URL=http://localhost:11434/v1
143150
# ENGRAPHIS_LLM_BASE_URL=https://openrouter.ai/api/v1
144151
# Optional: extra headers (JSON string) for custom providers.
145152
# ENGRAPHIS_LLM_EXTRA_HEADERS={"HTTP-Referer":"https://myapp.com","X-Title":"engraphis"}
@@ -179,15 +186,15 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
179186
# The plan is resolved automatically: once this installation has reached the control plane
180187
# it reads the authoritative entitlement (plan and feature list) and caches it beside the
181188
# cloud session, so a Pro or Team badge is correct on every later boot including offline
182-
# ones. The refresh is opportunistic and runs on a background thread — it never blocks or
189+
# ones. The refresh is opportunistic and runs on a background thread. It never blocks or
183190
# delays startup, and it never fails the dashboard when the cloud is unreachable. Before
184191
# the very first successful contact a connected installation is presented as Pro, the
185192
# smallest paid plan, so a paying customer is never shown the free local core.
186193
#
187194
# ENGRAPHIS_CLOUD_PLAN is an override for the cases automatic resolution cannot cover: an
188195
# air-gapped deployment, or one pinned to a short-lived ENGRAPHIS_CLOUD_ACCESS_TOKEN that
189196
# cannot refresh. It takes precedence over the cached entitlement. Accepts pro, team, or
190-
# free. It is presentation only — setting it grants nothing, because Engraphis Cloud
197+
# free. It is presentation only. Setting it grants nothing, because Engraphis Cloud
191198
# authorizes every paid call regardless of what this client displays.
192199
# ENGRAPHIS_CLOUD_PLAN=team
193200
#
@@ -208,7 +215,7 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
208215
# snapshots, while an installation connected to Engraphis Cloud is allowed by default,
209216
# because connecting already accepts the terms covering managed analytics, dreaming, and
210217
# consolidation. This variable is an explicit operator override, not a customer-facing
211-
# setting set it to 0 to opt a connected installation back out, or to 1 to force
218+
# setting: set it to 0 to opt a connected installation back out, or to 1 to force
212219
# managed compute on regardless of session state. The cloud service remains authoritative
213220
# for all paid computation.
214221
# ENGRAPHIS_MANAGED_COMPUTE_CONSENT=0
@@ -220,36 +227,36 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
220227
# These settings are used by advanced deployments, operators, and internal
221228
# subsystems. Leave commented unless your deployment needs them.
222229

223-
# Logging defaults to INFO, text format.
230+
# Logging: defaults to INFO, text format.
224231
# ENGRAPHIS_LOG_LEVEL=INFO
225232
# ENGRAPHIS_LOG_FORMAT=text
226233
# ENGRAPHIS_LOG_JSON=0
227234

228-
# CORS comma-separated origins allowed to call the dashboard REST API.
235+
# CORS: comma-separated origins allowed to call the dashboard REST API.
229236
# Default: http://127.0.0.1:<ENGRAPHIS_PORT> and
230237
# http://localhost:<ENGRAPHIS_PORT>. Explicit values replace both loopback origins.
231238
# ENGRAPHIS_CORS_ORIGINS=https://myapp.example.com
232239

233-
# Rate limiting requests per window. Default: 0 (disabled), with a 60s window
240+
# Rate limiting: requests per window. Default: 0 (disabled), with a 60s window
234241
# used when ENGRAPHIS_RATE_LIMIT is set above zero.
235242
# ENGRAPHIS_RATE_LIMIT=0
236243
# ENGRAPHIS_RATE_WINDOW=60
237244

238-
# HTTPS security origin used for HTTP-to-HTTPS redirects and security headers.
245+
# HTTPS security origin: used for HTTP-to-HTTPS redirects and security headers.
239246
# ENGRAPHIS_PUBLIC_URL wins; when unset, security falls back to
240247
# ENGRAPHIS_DASHBOARD_URL, then the legacy ENGRAPHIS_RELAY_PUBLIC_URL setting.
241248
# These settings do not change CORS; configure ENGRAPHIS_CORS_ORIGINS separately.
242249
# ENGRAPHIS_PUBLIC_URL=https://engraphis.example.com
243250
# ENGRAPHIS_RELAY_PUBLIC_URL=https://relay.example.com
244251

245-
# Trusted local peers comma-separated addresses exempt from rate limiting.
252+
# Trusted local peers: comma-separated addresses exempt from rate limiting.
246253
# ENGRAPHIS_LOCAL_TRUSTED_PEERS=127.0.0.1,::1
247254

248-
# Import roots semicolon-separated (Windows) or colon-separated (POSIX)
255+
# Import roots: semicolon-separated (Windows) or colon-separated (POSIX)
249256
# directories allowed as import sources.
250257
# ENGRAPHIS_IMPORT_ROOTS=/srv/docs:/home/user/notes
251258

252-
# Memory engine tuning decay halflife (days), chunk sizing (tokens),
259+
# Memory engine tuning: decay halflife (days), chunk sizing (tokens),
253260
# proactive context loop, and reranker model.
254261
# ENGRAPHIS_DECAY_HALFLIFE_DAYS=30
255262
# ENGRAPHIS_CHUNK_TOKENS=512
@@ -263,15 +270,15 @@ ENGRAPHIS_LLM_API_KEY=sk-your-key-here
263270
# ENGRAPHIS_LOOP_TOP_K=10
264271
# ENGRAPHIS_RERANK_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2
265272

266-
# Workspace allow-list comma-separated names. Empty = all allowed.
273+
# Workspace allow-list: comma-separated names. Empty = all allowed.
267274
# ENGRAPHIS_WORKSPACES=acme,personal
268275

269-
# Cloud Sync relay endpoint and optional token for self-hosted relay.
276+
# Cloud Sync relay: endpoint and optional token for self-hosted relay.
270277
# ENGRAPHIS_RELAY_URL=https://relay.example.com
271278
# ENGRAPHIS_SYNC_TOKEN=
272279
# ENGRAPHIS_SYNC_READ_ONLY=0
273280

274-
# Hosted plan upgrade URLs override the default upgrade landing pages.
281+
# Hosted plan upgrade URLs: override the default upgrade landing pages.
275282
# ENGRAPHIS_UPGRADE_URL=
276283
# ENGRAPHIS_PRO_UPGRADE_URL=
277284
# ENGRAPHIS_TEAM_UPGRADE_URL=

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
strategy:
1616
fail-fast: false
1717
matrix:
18-
python-version: ["3.10", "3.11", "3.12"]
18+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
1919
steps:
2020
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
2121
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
name: Public benchmarks
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
suite:
7+
description: "Protected benchmark suite to run"
8+
required: true
9+
type: choice
10+
options:
11+
- hosted-luna-full
12+
run_id:
13+
description: "Unique operator-supplied run identifier"
14+
required: true
15+
type: string
16+
max_hosted_calls:
17+
description: "Exact full-run call ceiling reported by the frozen dry-run"
18+
required: true
19+
type: string
20+
prerequisites_reviewed:
21+
description: "Smoke and pilot reports were completed and reviewed"
22+
required: true
23+
type: boolean
24+
default: false
25+
26+
permissions:
27+
contents: read
28+
29+
concurrency:
30+
group: public-benchmark-${{ inputs.suite }}-${{ inputs.run_id }}
31+
cancel-in-progress: false
32+
33+
jobs:
34+
benchmark:
35+
name: ${{ inputs.suite }} / ${{ inputs.run_id }}
36+
environment: public-benchmark-protected
37+
runs-on: [self-hosted, benchmark]
38+
timeout-minutes: 1440
39+
steps:
40+
- name: Check out the requested revision
41+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
42+
with:
43+
fetch-depth: 0
44+
45+
- name: Verify immutable clean source
46+
shell: bash
47+
run: |
48+
set -euo pipefail
49+
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
50+
test -z "$(git status --porcelain=v1 --untracked-files=all)"
51+
52+
- name: Set up Python
53+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
54+
with:
55+
python-version: "3.11"
56+
57+
- name: Install the protected benchmark environment
58+
run: |
59+
python -m pip install --upgrade pip
60+
python -m pip install -e ".[all,test,hosted-eval]"
61+
62+
- name: Create persistent private working directories
63+
shell: bash
64+
env:
65+
RUN_ID: ${{ inputs.run_id }}
66+
AUTHORIZED_CALLS: ${{ inputs.max_hosted_calls }}
67+
PREREQUISITES_REVIEWED: ${{ inputs.prerequisites_reviewed }}
68+
STATE_ROOT: ${{ vars.ENGRAPHIS_BENCHMARK_STATE_ROOT }}
69+
run: |
70+
set -euo pipefail
71+
if [[ ! "$RUN_ID" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]]; then
72+
echo "run_id must start with an alphanumeric and contain at most 128 safe characters" >&2
73+
exit 2
74+
fi
75+
if [[ ! "$AUTHORIZED_CALLS" =~ ^[1-9][0-9]*$ ]]; then
76+
echo "max_hosted_calls must be an explicit positive integer" >&2
77+
exit 2
78+
fi
79+
if [ "$PREREQUISITES_REVIEWED" != "true" ]; then
80+
echo "smoke and pilot prerequisites must be reviewed before a full run" >&2
81+
exit 2
82+
fi
83+
if [ -z "$STATE_ROOT" ] || [[ "$STATE_ROOT" == *$'\n'* ]]; then
84+
echo "ENGRAPHIS_BENCHMARK_STATE_ROOT must be configured on the protected runner" >&2
85+
exit 2
86+
fi
87+
mkdir -p -- "$STATE_ROOT"
88+
state_root_real="$(realpath "$STATE_ROOT")"
89+
workspace_real="$(realpath "$GITHUB_WORKSPACE")"
90+
if [ "$state_root_real" = "/" ] || [ "$state_root_real" = "$workspace_real" ] || \
91+
[[ "$state_root_real" == "$workspace_real/"* ]]; then
92+
echo "benchmark state must be outside the checkout" >&2
93+
exit 2
94+
fi
95+
state_dir="$state_root_real/$RUN_ID"
96+
mkdir -p -- "$state_dir"
97+
chmod 700 "$state_root_real" "$state_dir"
98+
printf 'BENCHMARK_STATE_DIR=%s\n' "$state_dir" >> "$GITHUB_ENV"
99+
mkdir -p public-artifacts
100+
101+
- name: Safe orchestrator dry-run (zero hosted calls)
102+
shell: bash
103+
env:
104+
AUTHORIZED_CALLS: ${{ inputs.max_hosted_calls }}
105+
run: |
106+
set -euo pipefail
107+
python -m eval.hosted_luna --dry-run --full \
108+
> "$BENCHMARK_STATE_DIR/plan.json"
109+
python - <<'PY'
110+
import json
111+
import os
112+
from pathlib import Path
113+
114+
path = Path(os.environ["BENCHMARK_STATE_DIR"]) / "plan.json"
115+
plan = json.loads(path.read_text(encoding="utf-8"))
116+
if plan.get("dry_run") is not True:
117+
raise SystemExit("orchestrator did not report dry_run=true")
118+
if plan.get("config", {}).get("stage") != "full":
119+
raise SystemExit("orchestrator dry-run did not bind the full stage")
120+
calls = plan.get("config", {}).get("projected_max_hosted_calls")
121+
if not isinstance(calls, int) or calls <= 0:
122+
raise SystemExit("dry-run did not provide a positive call ceiling")
123+
if str(calls) != os.environ["AUTHORIZED_CALLS"]:
124+
raise SystemExit("operator ceiling does not exactly match the frozen dry-run")
125+
(path.parent / "max-hosted-calls").write_text(str(calls), encoding="ascii")
126+
PY
127+
128+
- name: Execute the frozen benchmark plan
129+
shell: bash
130+
run: |
131+
set -euo pipefail
132+
max_calls="$(cat "$BENCHMARK_STATE_DIR/max-hosted-calls")"
133+
test "$max_calls" -gt 0
134+
python -m eval.hosted_luna --full \
135+
--max-hosted-calls "$max_calls" \
136+
--private-records "$BENCHMARK_STATE_DIR/records.jsonl" \
137+
--public-report "$BENCHMARK_STATE_DIR/public.json"
138+
139+
- name: Validate the public artifact and its claim boundary
140+
shell: bash
141+
env:
142+
RUN_ID: ${{ inputs.run_id }}
143+
run: |
144+
set -euo pipefail
145+
python -m eval.public_readiness \
146+
--artifact "$BENCHMARK_STATE_DIR/public.json"
147+
cp "$BENCHMARK_STATE_DIR/public.json" "public-artifacts/$RUN_ID.json"
148+
sha256sum "public-artifacts/$RUN_ID.json" > "public-artifacts/$RUN_ID.json.sha256"
149+
150+
- name: Upload redacted public artifacts only
151+
if: ${{ success() }}
152+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
153+
with:
154+
name: public-benchmark-${{ inputs.suite }}-${{ inputs.run_id }}
155+
path: public-artifacts/
156+
if-no-files-found: error
157+
retention-days: 14

0 commit comments

Comments
 (0)