Skip to content

Keep expire-save failures live; lossless snapshot, WHERE, ACL who - #202

Merged
chouswei merged 12 commits into
masterfrom
cursor/engine-snapshot-where-acl-44e2
Oct 8, 2026
Merged

chouswei merged 12 commits into
masterfrom
cursor/engine-snapshot-where-acl-44e2

Conversation

@chouswei

@chouswei chouswei commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Patch-level honesty cut on 0.19.18 (no version bump, tag, or PyPI publish). Follow-on from the doc-gate readiness probe in #201 (squash-merged as 8a634d3). This branch is rebased onto that master. SysML first: MN-REQ-01.9, MN-REQ-01.3, MN-REQ-01.10, MN-REQ-03.4, MN-REQ-05.3, then engine. Do not merge.

Owner decision — expire-save failure keeps RAM

When save-on-expire cannot write a snapshot (snapshot_unsaveable or any other save failure, such as an unwritable disk or directory), MemNet does not drop the session. It stays live in RAM, still counts against MEMNET_MAX_SESSIONS, and every sweep or access that retries expiry emits @WRN: expire_snapshot_failed|{code}. Access after TTL is @ERR: session_expired|overdue so the caller can fix and save, or close. An explicit session save that succeeds, or an explicit session close, ends that hold. session expire-status, session list, and the admin usage report expose the hold count (@STAT: expire_snapshot_failed|n| / sessions.expire_snapshot_failed). When save-on-expire is off, TTL still drops RAM.

Tests (in-process and live serve loopback): unsaveable expiry keeps and warns; later fix plus save clears; close clears; the held session still counts against the cap.

Endleaf compatibility — WHERE true

Endleaf's gate deletes edges with MATCH (n WHERE true)-[r {id:'…'}]->() DELETE r and never sends any other WHERE. Trivial WHERE true is honoured (not unsupported_predicate). In-process test_where_true_edge_delete_still_works and live test_endleaf_where_true_edge_delete use that exact spelling.

Bug 1 — snapshot save/load round-trip

Anything the write path accepts now saves and reloads byte for byte, including LF, CR, tab, VT, FF, FS/GS/RS, NEL, LS, PS, backslash, both quote kinds, $, braces, |, and CJK.

  • Snapshot emit escapes every Python str.splitlines() separator plus | and \\; load splits records on LF only (not str.splitlines()).
  • Undeclared RAM properties (GraphElement extras; Path-B locators such as qname) persist by widening the snapshot SCHEMA. Live session SCHEMA is unchanged. Extras on fixed tags EDG/LAW, or a widened SCHEMA over max_fields, refuse snapshot_unsaveable and write no file.
  • One hard value cap across leftover pipe mutate, GQL mutate, and snapshot load: decoded raw UTF-8 of the property value. Knob MEMNET_MAX_VALUE_BYTES (default 4096; a product MAY raise it to 16384).
  • GQL mutate refuses over-cap with @ERR: limit_exceeded|value_bytes {n}/{max}.
  • line_bytes is the UTF-8 length of the escaped/raw leftover-pipe or snapshot line. Save verify and load share this check.
  • Save fails closed: @ERR: snapshot_unsaveable|{tag} nick={nick} … and no file.

Bug 2 — MATCH WHERE SET/DELETE

WHERE is honoured or the whole statement is refused. Nothing is applied on refuse. MATCH ()-[r {id}]-() DELETE r honours relationship DELETE. MATCH (n WHERE true)-[r {id}]->() DELETE r remains the gated edge-delete spelling.

Bug 3 — ACL on save / load / close

When session ACL is enabled, session save, session load (into that ACL'd session), and session close accept --caller / MEMNET_CALLER and enforce acl_who / acl_denied / acl_forbidden. MCP passes caller. Without ACL, behaviour is unchanged.

#201 probe / docs flipped (not skipped)

tests/test_doc_gate_readiness.py, tests/doc_gate_lib.py, scripts/probe_doc_gate_readiness.py, and docs/operations/one-session-per-document.md now expect the fixed behaviour: multiline/CR round-trip, 16 KiB refused at mutate (value_bytes 16384/4096), WHERE honoured, ACL who on save/close, extras persist or refuse at save over max_fields. Expire-save failure keep-live is also taught there and in docs/cap-contract.md.

Synthetic data only. No real mn_… session ids in the tree.

Open in Web Open in Cursor 

cursoragent and others added 9 commits October 8, 2026 14:27
SysML-first honesty cut: lossless snapshot round-trip, honour-or-refuse
WHERE, consistent decoded value_bytes cap, and who-check on session
save/load/close. Verify cases MN-VER-01-S04, 01-S05, 03-S01, 05-S01.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
Snapshot emit escapes LF/CR/pipe/backslash; load decodes; save fails closed
with snapshot_unsaveable. GQL mutate shares MEMNET_MAX_VALUE_BYTES on decoded
UTF-8. MATCH WHERE SET/DELETE honours the predicate or refuses
unsupported_predicate with nothing applied. Session save/load/close accept
--caller when ACL is enabled; MCP passes caller through.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
Pytest covers lossless specials, 0.19.18 fixture load, GQL value_bytes,
unsupported_predicate, fail-closed save, and session save/load/close ACL.
Cap-contract probe hits the new wires; bug 4 (GQL mutate skipping the
value cap) is removed.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
Co-authored-by: chouswei <chouswei@users.noreply.github.com>
… check line_bytes at save.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
…ite-time line_bytes.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
Co-authored-by: chouswei <chouswei@users.noreply.github.com>
…HERE, and ACL who.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
…TE in E16.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/engine-snapshot-where-acl-44e2 branch from bfb986b to f38746c Compare October 8, 2026 14:43
Expire-save failure (snapshot_unsaveable or OSError) no longer drops RAM.
The session still counts against MEMNET_MAX_SESSIONS, retries warn
expire_snapshot_failed, and access after TTL is session_expired|overdue
until an explicit successful save or close. Save-on-expire off is unchanged.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
@cursor cursor Bot changed the title Fix snapshot round-trip, MATCH WHERE, and session ACL who-check Keep expire-save failures live; lossless snapshot, WHERE, ACL who Oct 8, 2026
cursoragent and others added 2 commits October 8, 2026 15:07
Serve @err replaces inner pipes with spaces; the hold still counts against MEMNET_MAX_SESSIONS.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
Trivial WHERE true stays honoured, not unsupported_predicate. In-process and live serve loopback cover the exact no-space id map spelling the gate sends.

Co-authored-by: chouswei <chouswei@users.noreply.github.com>
@chouswei
chouswei marked this pull request as ready for review October 8, 2026 15:14
@chouswei
chouswei merged commit 300f086 into master Oct 8, 2026
2 checks passed
chouswei added a commit that referenced this pull request Oct 8, 2026
Hatch, project.toml, changelog, and the version map name the #201 doc-gate readiness probe and the #202 snapshot / value cap / WHERE / ACL who / expire-save fixes. Not 0.20.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants