Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
30e3a0f
Fold every Classic dashboard feature into Ledger and retire Classic
Coding-Dev-Tools Oct 12, 2026
9ba6532
Refuse DNS-rebinding hosts on the token-free local servers
Coding-Dev-Tools Oct 12, 2026
4d982f9
Reconcile the Claude Ledger work with Spec Studio and dashboard fixes
Coding-Dev-Tools Oct 12, 2026
679dcbb
Bind the desktop integration evidence to its committed source
Coding-Dev-Tools Oct 12, 2026
26bb401
Carry the reviewed graph cancellation fix into the desktop stack
Coding-Dev-Tools Oct 12, 2026
22ce45e
Preserve editor drafts across workspace metadata updates
Coding-Dev-Tools Oct 12, 2026
a1af2b2
Confirm active workspace renames and preserve chained dialogs
Coding-Dev-Tools Oct 12, 2026
f1f85a4
Keep graph explorer navigation within the visible scope
Coding-Dev-Tools Oct 12, 2026
de8c168
Preserve drafts across workspace mutations and maintenance refreshes
Coding-Dev-Tools Oct 12, 2026
880e0f6
Filter superseded timeline history before result limits
Coding-Dev-Tools Oct 12, 2026
606d3e5
Pin benchmark links to the timeline filtering source
Coding-Dev-Tools Oct 12, 2026
b3d541b
Respect watchdog timeouts and keep graph legends within scope
Coding-Dev-Tools Oct 12, 2026
95999cb
Pin benchmark documentation to watchdog and legend repairs
Coding-Dev-Tools Oct 12, 2026
96b25e0
Validate complete browser origins and order fallback timelines
Coding-Dev-Tools Oct 12, 2026
f07db1f
Pin benchmark documentation to complete-origin validation
Coding-Dev-Tools Oct 12, 2026
3eeb5b5
Keep scheduled future expiry out of superseded timelines
Coding-Dev-Tools Oct 12, 2026
7a1b05e
Pin benchmark documentation to world-time timeline filtering
Coding-Dev-Tools Oct 12, 2026
ec71481
Preserve Unix-epoch dates in the dashboard
Coding-Dev-Tools Oct 12, 2026
986bb29
Keep graph community labels stable and focus newly revealed relations
Coding-Dev-Tools Oct 14, 2026
45fe1f5
Integrate audit, import polling, and settled-renderer safeguards into…
Coding-Dev-Tools Oct 14, 2026
e8756e6
Integrate the documentation contract corrections into Ledger
Coding-Dev-Tools Oct 14, 2026
f7e3a93
Publish fresh immutable evidence for PR #262
Coding-Dev-Tools Oct 14, 2026
12102ec
Pin chart links to the verified PR evidence source
Coding-Dev-Tools Oct 14, 2026
2702662
Match legend regression expectations to stable canvas community ident…
Coding-Dev-Tools Oct 14, 2026
d86590c
Integrate dashboard evidence from exact committed source bytes
Coding-Dev-Tools Oct 14, 2026
dfa3151
Publish fresh immutable evidence for PR #262
Coding-Dev-Tools Oct 14, 2026
c384870
Pin chart links to the verified PR evidence source
Coding-Dev-Tools Oct 14, 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
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,11 @@ ENGRAPHIS_LLM_MODEL=gpt-4o-mini
# http://localhost:<ENGRAPHIS_PORT>. Explicit values replace both loopback origins.
# ENGRAPHIS_CORS_ORIGINS=https://myapp.example.com

# Without ENGRAPHIS_API_TOKEN, the dashboard API and read-only graph server answer only
# localhost, IP addresses, the bind host, the ENGRAPHIS_DASHBOARD_URL host and these extra
# comma-separated names, so a website using DNS rebinding cannot reach them.
# ENGRAPHIS_ALLOWED_HOSTS=engraphis.lan,my-desktop

# Rate limiting: requests per window. Default: 0 (disabled), with a 60s window
# used when ENGRAPHIS_RATE_LIMIT is set above zero.
# ENGRAPHIS_RATE_LIMIT=0
Expand Down
6 changes: 3 additions & 3 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Warn-only design-slop check for the Engraphis dashboard.
#
# Runs ONLY when engraphis/static/index.html is staged, and NEVER blocks the
# Runs ONLY when engraphis/dashboard_assets/index.html is staged, and NEVER blocks the
# commit — it prints a summary and always exits 0. Warn-only is deliberate: the
# automated development workflows may commit, and a blocking hook would break
# those unattended commits. For a hard gate on your own manual commits, run
Expand All @@ -12,9 +12,9 @@
set -uo pipefail

staged="$(git diff --cached --name-only 2>/dev/null || true)"
printf '%s\n' "$staged" | grep -q 'engraphis/static/index\.html' || exit 0
printf '%s\n' "$staged" | grep -q 'engraphis/dashboard_assets/index\.html' || exit 0

if [ -f scripts/design-lint.sh ]; then
bash scripts/design-lint.sh engraphis/static/index.html || true
bash scripts/design-lint.sh engraphis/dashboard_assets/index.html || true
fi
exit 0
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ most common mistake here.
|---|---|---|
| Status | Primary scoped, bi-temporal, interface-driven implementation. | Compatibility/reference implementation with flat namespaces. |
| Model | Scoped + bi-temporal + typed; interface-driven. | Single flat `namespace` string per memory. |
| Code | `engraphis/core/`, `engraphis/backends/`, `eval/`, `tests/`, `scripts/migrate_to_v2.py` | `engraphis/app.py`, `config.py`, `models.py`, `routes/`, `stores/`, `engines/`, `llm/`, `static/` |
| Code | `engraphis/core/`, `engraphis/backends/`, `eval/`, `tests/`, `scripts/migrate_to_v2.py` | `engraphis/app.py`, `config.py`, `models.py`, `routes/`, `stores/`, `engines/`, `llm/` |
| Data | new v2 schema (`SCHEMA_VERSION = 18`) | `engraphis_v1.db` |
| Entry | `engraphis.MemoryEngine.create()` / `engraphis.create_memory_engine()` → `engraphis/factory.py` → `core/engine.py` | Internal reference only; never a public launcher |

Expand Down
10 changes: 5 additions & 5 deletions BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ interpretation and do not count as additional benchmark-quality gains.
### Public numeric evidence registry

Every exact public aggregate retained below comes from the checked-in, public-safe
[`offline-fixtures-pr261-git-bytes-20261014.json`](docs/benchmark-evidence/offline-fixtures-pr261-git-bytes-20261014.json) artifact. Its
[`offline-fixtures-pr262-git-bytes-20261014.json`](docs/benchmark-evidence/offline-fixtures-pr262-git-bytes-20261014.json) artifact. Its
SHA-256 is
`998a65945b85d8fb91287474389b14bb908057f1ed06d75d79260027f1bcd11d`, also recorded in the
`1b4ba1d95ae003bab4c5d15a7d619fc7a7b813d66387bc9530a74babad5221eb`, also recorded in the
adjacent `.sha256` file. The artifact contains no raw questions, answers, prompts, customer data,
or per-record content fingerprints.

The fixture-suite digest is
`cff9ddc5c861f217ca7624ab0a0e301a813147a2c49a52a7991a3e3dd532b9ea`. The artifact defines
`e5f78cc61a584b64051cc8650c8e2f68cff9a3ccb096df57e8a621d376f829b8`. The artifact defines
the digest algorithm and records the SHA-256 of every suite and dataset file. Each evidence ID
also binds its exact command through `sha256(UTF-8 exact command)`:

Expand All @@ -126,13 +126,13 @@ grounded checks in separate panels; provider billing and MCP transport are not m
the SVG and matching PNG with:

```bash
python scripts/render_benchmark_report.py --report docs/benchmark-evidence/offline-fixtures-pr261-git-bytes-20261014.json --output docs/images/context-efficiency.svg --png-output docs/images/context-efficiency.png
python scripts/render_benchmark_report.py --report docs/benchmark-evidence/offline-fixtures-pr262-git-bytes-20261014.json --output docs/images/context-efficiency.svg --png-output docs/images/context-efficiency.png
```

The companion examples are also generated from that artifact with:

```bash
python -m scripts.render_benchmark_examples --report docs/benchmark-evidence/offline-fixtures-pr261-git-bytes-20261014.json --output docs/images/evidence-backed-agent-examples.svg --png-output docs/images/evidence-backed-agent-examples.png
python -m scripts.render_benchmark_examples --report docs/benchmark-evidence/offline-fixtures-pr262-git-bytes-20261014.json --output docs/images/evidence-backed-agent-examples.svg --png-output docs/images/evidence-backed-agent-examples.png
```
The historical-to-executable mapping is in
[`docs/BENCHMARK_CHANGE_COVERAGE.md`](docs/BENCHMARK_CHANGE_COVERAGE.md).
Expand Down
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,52 @@ All notable changes to Engraphis are documented here. Format loosely follows

## [Unreleased]

- The dashboard has one interface. Every capability of the former Classic dashboard now lives
in Ledger, and `/classic` redirects to it. The `engraphis/classic_assets/` and duplicate
`engraphis/static/` asset trees, the dashboard switcher and the bundled Marked and DOMPurify
copies are removed; memory Markdown is rendered by a small DOM-only renderer that never
parses HTML.
- Ledger adds: Markdown rendering with an editor Preview toggle, an unsaved-changes guard and
Ctrl/Cmd+S; word-level diffs between saved versions; each memory's audit trail; drag and
Alt+Arrow ordering in the Library; Quick import (drag-and-drop files and folders, or a
folder path on the machine running Engraphis) and a Code and database sources dialog
(repository indexing and PostgreSQL schema import; the connection string is never stored);
retrieval scores in Ask; bi-temporal Timeline cards with a superseded-only filter, which
replaces the separate Supersessions tab; inline receipt-chain status and packed-context
accounting; Home memory health and the selected project's last-session handoff; workspace
Describe, Merge, Export and Open library actions; plan status, automation run status and
on-demand proposals; connection-lost and semantic-search-off banners; graph colour modes,
palettes, editable entity-type colours, a legend, an entity and relation explorer and canvas
keyboard navigation; and Solarized and Sepia themes.
- Confirmations and prompts use one accessible in-page dialog instead of the browser's native
boxes. Deleting a workspace now says plainly that it is a permanent hard delete, and the
copy and import summaries report the counts the API actually returns.
- `GET /api/proactive` accepts an optional `repo` and returns that project's last-session
handoff, or `null`; before, the dashboard could only ever receive an empty handoff.
- The dashboard CSP release gate (`scripts/externalize_dashboard_assets.py`) now checks the
Ledger page and every first-party dashboard script, and rejects HTML string injection in
all its forms (`+=`, bracket and object-literal property writes, `document.write`,
`DOMParser`, `srcdoc`) and inline style or handler attributes in any letter case.
- Security: without `ENGRAPHIS_API_TOKEN`, the dashboard API refuses requests that a browser
marks as started by another website unless they carry the dashboard's session header or an
`Authorization` header, both of which need a CORS preflight. Another website can no longer
make a visitor's browser import files, start a sync or hosted upload, or change LLM settings
on a zero-config loopback install, even when `ENGRAPHIS_CORS_ORIGINS` is `*`. Without a
token the dashboard API, its `/dashboard/review` routes and the read-only graph server also
answer only exactly `localhost`, IP addresses, the bind host, the `ENGRAPHIS_DASHBOARD_URL`
host and the new `ENGRAPHIS_ALLOWED_HOSTS` names, so DNS rebinding (a website pointing its
own name at 127.0.0.1) cannot reach them either. The Markdown renderer is bounded (linear scans, an index
of backtick runs, capped tables and element counts), so crafted memory content cannot freeze
the page used to review it. Dialogs drop bidirectional control
characters from untrusted names, and an invalid timestamp reads as unknown instead of
breaking the Timeline and Why panels.
- Fixes: Secure erase from the dashboard sends the confirmation the service requires (it
always failed before); a failed d3 download is retried by Reload, and a stalled graph
download no longer blocks the next attempt; the Every-node view applies the same Unlinked
nodes and Minimum links rules as the overview; entity-type colours follow the active theme;
leaving the editor while a save is in flight asks first, and a save that fails after you
leave is still reported.

## [1.7.9] - 2026-09-29

- Classify local `engraphis_decide` command advice conservatively. Chained, piped,
Expand Down
4 changes: 0 additions & 4 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
global-exclude *.pyc
global-exclude *.pyo

recursive-include engraphis/static *.html *.css *.js *.png *.ico
recursive-include engraphis/static/vendor *
recursive-include engraphis/classic_assets *.html *.css *.js *.png *.ico
recursive-include engraphis/classic_assets/vendor *
recursive-include engraphis/dashboard_assets *.html *.css *.js *.png *.ico
recursive-include engraphis/dashboard_assets/vendor *
include engraphis/commercial_manifest.json
Expand Down
8 changes: 2 additions & 6 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@ The Apache-2.0 license does not grant trademark rights (see LICENSE, section 6).
Third-party browser assets distributed with this product:

- D3 7.9.0, Copyright 2010-2023 Mike Bostock, ISC license. See
engraphis/static/vendor/d3.LICENSE.
- Marked 12.0.2, Copyright MarkedJS, Christopher Jeffrey, and Markdown's
contributors, MIT and BSD-style licenses. See engraphis/static/vendor/marked.LICENSE.
engraphis/dashboard_assets/vendor/d3.LICENSE.
- force-graph 1.51.4 and its bundled runtime dependency closure, MIT/ISC/BSD-3-Clause
licenses. See engraphis/static/vendor/force-graph.LICENSE and the complete
licenses. See engraphis/dashboard_assets/vendor/force-graph.LICENSE and the complete
machine-verifiable notices in deploy/force-graph-1.51.4.licenses.json, derived from
deploy/force-graph-1.51.4.yarn.lock at upstream commit
baa20a92bbe5628034d771abaf33a2dbb65d22eb.
- DOMPurify 3.4.11, Copyright Cure53 and contributors, distributed under the
Apache License 2.0 option stated in its embedded license header; see LICENSE.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ Connect a coding agent over MCP with the [agent setup guide](https://github.com/
- **Continuity:** Organize memories by workspace, repository, and session, with a last-session handoff.
- **Useful recall:** Combine vector, lexical, graph, and code-aware retrieval, then pack results to a hard context budget.
- **Grounded answers:** Preserve provenance and temporal history; cite support or abstain when it is insufficient.
- **Temporal history:** Timeline can select known versions whose validity has ended before result limits. The dashboard uses `closed_only=true` on `GET /api/timeline` for “Only superseded versions.”
- **Operator control:** Keep the core local and offline-capable, with explicit controls for hosted services and external LLM providers.

## Benchmarks

The current registered artifact contains three deterministic offline fixture runs. It separates context size, retrieval quality, and grounded decision checks; these small fixtures do not establish general task performance.

<p align="center">
<img src="https://raw.githubusercontent.com/Coding-Dev-Tools/engraphis/a07ca9ad2d0be588b4595c2f14a7292ea4a9ac7d/docs/images/context-efficiency.svg" alt="Three registered offline fixtures: structure-aware chunking reduced mean retrieved context from 740.3 to 214.3 tokens per question (71.1%, 18 questions); the serialized JSON-shape proxy fell from 24,590 to 11,138 tokens across 26 payload samples and 260 recalls. Candidate and packed retrieval quality (Recall@5, Hit@5, and answer-token recall) are shown separately (each 1.000). Grounded checks show 5/5 answerable queries grounded and 6/6 abstention queries rejected, including a 1/1 quarantined-evidence probe; 11/11 decisions were correct. MCP transport and provider billing were not measured. Artifact SHA-256 prefix 998a65945b85; see the benchmark guide for the full checksum." width="100%">
<img src="https://raw.githubusercontent.com/Coding-Dev-Tools/engraphis/dfa3151d06ca3c226b50bc2e43305f4b23d42903/docs/images/context-efficiency.svg" alt="Three registered offline fixtures: structure-aware chunking reduced mean retrieved context from 740.3 to 214.3 tokens per question (71.1%, 18 questions); the serialized JSON-shape proxy fell from 24,590 to 11,138 tokens across 26 payload samples and 260 recalls. Candidate and packed retrieval quality (Recall@5, Hit@5, and answer-token recall) are shown separately (each 1.000). Grounded checks show 5/5 answerable queries grounded and 6/6 abstention queries rejected, including a 1/1 quarantined-evidence probe; 11/11 decisions were correct. MCP transport and provider billing were not measured. Artifact SHA-256 prefix 1b4ba1d95ae0; see the benchmark guide for the full checksum." width="100%">
<br>
<sup>Three offline fixtures separate context reduction, candidate and packed retrieval quality, and grounded behavior. The chart shows the artifact checksum prefix; see the benchmark guide for the full checksum and reproduction steps.</sup>
</p>
Expand All @@ -60,7 +61,7 @@ The current registered artifact contains three deterministic offline fixture run
| Recall payload proxy | JSON-shape proxy: 24,590 → 11,138 tokens (54.71% lower, 26 samples; 260 timed recalls) | Candidate and packed Recall@5, Hit@5, and answer-token recall are each 1.000 |
| Grounded decisions | 5/5 answerable queries grounded; 6/6 abstention queries rejected, including 1/1 quarantined-evidence check | 11/11 decisions correct |

The payload figure is a serialized JSON-shape estimate, not an MCP transport measurement or provider billing total. See the [Benchmark methodology](https://github.com/Coding-Dev-Tools/engraphis/blob/a07ca9ad2d0be588b4595c2f14a7292ea4a9ac7d/BENCHMARKS.md) for artifact identity, counting methods, reproduction commands, external-evaluation boundaries, and limitations.
The payload figure is a serialized JSON-shape estimate, not an MCP transport measurement or provider billing total. See the [Benchmark methodology](https://github.com/Coding-Dev-Tools/engraphis/blob/dfa3151d06ca3c226b50bc2e43305f4b23d42903/BENCHMARKS.md) for artifact identity, counting methods, reproduction commands, external-evaluation boundaries, and limitations.

## Optional Jev assistance

Expand Down
24 changes: 22 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@ Memories may originate from web pages, tool output, or other untrusted sources.
> detector bypass through ingest, and a mislabeled trusted case. Its metrics apply only to those
> declared synthetic cases.

**Dashboard XSS (fixed):** Memory content rendered as markdown is now sanitized via
DOMPurify at all render sites. Verified against payloads with `onerror` handlers.
**Dashboard XSS (fixed):** The dashboard renders memory content as Markdown with its own
DOM-only renderer (`engraphis/dashboard_assets/markdown.js`): it builds elements with
`textContent`, never parses HTML or assigns `innerHTML`, and links only absolute `http(s)` and
`mailto` URLs. Raw HTML in a memory is shown as text. The renderer is bounded (linear scans,
capped tables and element count) so crafted content cannot freeze the page used to review it;
`tests/test_markdown_renderer.py` exercises hostile and oversized inputs.

### 2. Network exposure & authentication
- **Loopback by default** (`ENGRAPHIS_HOST=127.0.0.1`)
Expand All @@ -62,6 +66,17 @@ DOMPurify at all render sites. Verified against payloads with `onerror` handlers
invitations, roles, named seats, token rotation, and organization audit are hosted and are
not mounted by this package.
- **CORS allow-list** defaults to loopback only
- **Cross-site browser requests refused without a token:** the zero-config API trusts loopback
callers, so it refuses requests that a browser marks (`Origin`, `Sec-Fetch-Site`) as started
by another website unless they carry the dashboard's `X-Engraphis-Browser-Session` header or
an `Authorization` header, which a cross-site page can only send after a CORS preflight.
Non-browser clients send neither marker and are unaffected.
- **Host names checked without a token:** the zero-config dashboard API (including its
`/dashboard/review` routes) and the token-free read-only graph server refuse requests
addressed to any name other than exactly `localhost`, an IP address, the bind host, the host
of `ENGRAPHIS_DASHBOARD_URL` or a name in `ENGRAPHIS_ALLOWED_HOSTS`, so a website that points
its own name at 127.0.0.1 (DNS rebinding) cannot use them. The `/mcp` endpoint keeps its own
Host allow-list. A configured API token is the boundary instead, under any name.
- If exposed beyond localhost: put behind reverse proxy with **TLS + rate limiting**

### 3. Scope isolation
Expand Down Expand Up @@ -105,6 +120,11 @@ installation, so do not share its bearer token.
- The import UI's `derive_facts` option is a separate explicit opt-in. If an LLM/custom
extractor is configured, selected file content may be sent to that provider; leave it off
for a strictly local import. The default and chunk extractors remain fully local.
- A multipart upload needs no CORS preflight, so `/api/workspaces/import-files` refuses
browser requests (those carrying `Origin` or `Sec-Fetch-Site`) unless they also carry the
dashboard's session header or an `Authorization` header. Another website therefore cannot
make a visitor's browser import files into a zero-config loopback install. Non-browser
clients are unaffected.
- Audio/video transcription runs only when `ENGRAPHIS_WHISPER_MODEL` is configured. Depending on
the faster-whisper model name, the underlying library may download a model; use an absolute
local model path when strictly offline operation is required.
Expand Down
2 changes: 1 addition & 1 deletion deploy/force-graph-1.51.4.licenses.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
"name": "force-graph",
"npm_integrity": "sha512-TdJ2KbkoiDQ7NIRx8IPGD0mAXXpLhamS7c+b7W98b0MHG7lphnda1VOQX/98UDTsttIAdH4TcP0l0MauSnLK8w==",
"path": "engraphis/static/vendor/force-graph.min.js",
"path": "engraphis/dashboard_assets/vendor/force-graph.min.js",
"sha256": "5b71387a1ebbe99a2e8c845cd6ac40f776e363dbcb6a4dd200001b70e7b7271e",
"upstream_commit": "baa20a92bbe5628034d771abaf33a2dbb65d22eb",
"version": "1.51.4"
Expand Down
Loading
Loading