compartment 4__tar.gz → 4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. {compartment-4 → compartment-4.1}/PKG-INFO +1 -1
  2. {compartment-4 → compartment-4.1}/pyproject.toml +1 -1
  3. {compartment-4 → compartment-4.1}/src/compartment/__init__.py +1 -1
  4. {compartment-4 → compartment-4.1}/src/compartment/store.py +17 -8
  5. {compartment-4 → compartment-4.1}/src/compartment.egg-info/PKG-INFO +1 -1
  6. {compartment-4 → compartment-4.1}/tests/test_long_memory_recall.py +38 -0
  7. {compartment-4 → compartment-4.1}/README.md +0 -0
  8. {compartment-4 → compartment-4.1}/setup.cfg +0 -0
  9. {compartment-4 → compartment-4.1}/src/compartment/acl.py +0 -0
  10. {compartment-4 → compartment-4.1}/src/compartment/agent_skill.py +0 -0
  11. {compartment-4 → compartment-4.1}/src/compartment/audit.py +0 -0
  12. {compartment-4 → compartment-4.1}/src/compartment/bench.py +0 -0
  13. {compartment-4 → compartment-4.1}/src/compartment/claude_desktop.py +0 -0
  14. {compartment-4 → compartment-4.1}/src/compartment/claude_hooks.py +0 -0
  15. {compartment-4 → compartment-4.1}/src/compartment/claude_memory.py +0 -0
  16. {compartment-4 → compartment-4.1}/src/compartment/cli.py +0 -0
  17. {compartment-4 → compartment-4.1}/src/compartment/crypto.py +0 -0
  18. {compartment-4 → compartment-4.1}/src/compartment/dash.py +0 -0
  19. {compartment-4 → compartment-4.1}/src/compartment/data/agent-skill/SKILL.md +0 -0
  20. {compartment-4 → compartment-4.1}/src/compartment/data/app.icns +0 -0
  21. {compartment-4 → compartment-4.1}/src/compartment/data/app.png +0 -0
  22. {compartment-4 → compartment-4.1}/src/compartment/data/hermes-plugin/__init__.py +0 -0
  23. {compartment-4 → compartment-4.1}/src/compartment/data/hermes-plugin/plugin.yaml +0 -0
  24. {compartment-4 → compartment-4.1}/src/compartment/data/menubar.png +0 -0
  25. {compartment-4 → compartment-4.1}/src/compartment/data/menubar@2x.png +0 -0
  26. {compartment-4 → compartment-4.1}/src/compartment/data/starter.mpack +0 -0
  27. {compartment-4 → compartment-4.1}/src/compartment/data/tray.ico +0 -0
  28. {compartment-4 → compartment-4.1}/src/compartment/embed.py +0 -0
  29. {compartment-4 → compartment-4.1}/src/compartment/home.py +0 -0
  30. {compartment-4 → compartment-4.1}/src/compartment/longmemeval.py +0 -0
  31. {compartment-4 → compartment-4.1}/src/compartment/menubar.py +0 -0
  32. {compartment-4 → compartment-4.1}/src/compartment/models/bge-small-en-v1.5-int8/model_quantized.onnx +0 -0
  33. {compartment-4 → compartment-4.1}/src/compartment/models/bge-small-en-v1.5-int8/tokenizer.json +0 -0
  34. {compartment-4 → compartment-4.1}/src/compartment/offline_guard.py +0 -0
  35. {compartment-4 → compartment-4.1}/src/compartment/packs.py +0 -0
  36. {compartment-4 → compartment-4.1}/src/compartment/platforms.py +0 -0
  37. {compartment-4 → compartment-4.1}/src/compartment/ranking.py +0 -0
  38. {compartment-4 → compartment-4.1}/src/compartment/salience.py +0 -0
  39. {compartment-4 → compartment-4.1}/src/compartment/selftest.py +0 -0
  40. {compartment-4 → compartment-4.1}/src/compartment/server.py +0 -0
  41. {compartment-4 → compartment-4.1}/src/compartment/session.py +0 -0
  42. {compartment-4 → compartment-4.1}/src/compartment/systray.py +0 -0
  43. {compartment-4 → compartment-4.1}/src/compartment/vault.py +0 -0
  44. {compartment-4 → compartment-4.1}/src/compartment/vaultfile.py +0 -0
  45. {compartment-4 → compartment-4.1}/src/compartment/vindex.py +0 -0
  46. {compartment-4 → compartment-4.1}/src/compartment/wire.py +0 -0
  47. {compartment-4 → compartment-4.1}/src/compartment.egg-info/SOURCES.txt +0 -0
  48. {compartment-4 → compartment-4.1}/src/compartment.egg-info/dependency_links.txt +0 -0
  49. {compartment-4 → compartment-4.1}/src/compartment.egg-info/entry_points.txt +0 -0
  50. {compartment-4 → compartment-4.1}/src/compartment.egg-info/requires.txt +0 -0
  51. {compartment-4 → compartment-4.1}/src/compartment.egg-info/top_level.txt +0 -0
  52. {compartment-4 → compartment-4.1}/tests/test_acl_audit_packs.py +0 -0
  53. {compartment-4 → compartment-4.1}/tests/test_acl_precedence.py +0 -0
  54. {compartment-4 → compartment-4.1}/tests/test_agent_skill.py +0 -0
  55. {compartment-4 → compartment-4.1}/tests/test_attempt_pacing.py +0 -0
  56. {compartment-4 → compartment-4.1}/tests/test_audit_chain.py +0 -0
  57. {compartment-4 → compartment-4.1}/tests/test_autoconnect.py +0 -0
  58. {compartment-4 → compartment-4.1}/tests/test_claude_desktop.py +0 -0
  59. {compartment-4 → compartment-4.1}/tests/test_claude_hooks_and_integrate.py +0 -0
  60. {compartment-4 → compartment-4.1}/tests/test_claude_memory_and_recent.py +0 -0
  61. {compartment-4 → compartment-4.1}/tests/test_connect_buttons.py +0 -0
  62. {compartment-4 → compartment-4.1}/tests/test_connect_environment.py +0 -0
  63. {compartment-4 → compartment-4.1}/tests/test_crypto.py +0 -0
  64. {compartment-4 → compartment-4.1}/tests/test_dash.py +0 -0
  65. {compartment-4 → compartment-4.1}/tests/test_instructions.py +0 -0
  66. {compartment-4 → compartment-4.1}/tests/test_journal_framing.py +0 -0
  67. {compartment-4 → compartment-4.1}/tests/test_linux_panel.py +0 -0
  68. {compartment-4 → compartment-4.1}/tests/test_login_item_identity.py +0 -0
  69. {compartment-4 → compartment-4.1}/tests/test_macos_bundle.py +0 -0
  70. {compartment-4 → compartment-4.1}/tests/test_menubar.py +0 -0
  71. {compartment-4 → compartment-4.1}/tests/test_offline_guard_paths.py +0 -0
  72. {compartment-4 → compartment-4.1}/tests/test_offline_selftest_bench.py +0 -0
  73. {compartment-4 → compartment-4.1}/tests/test_ondisk_format.py +0 -0
  74. {compartment-4 → compartment-4.1}/tests/test_pack_trust.py +0 -0
  75. {compartment-4 → compartment-4.1}/tests/test_platforms.py +0 -0
  76. {compartment-4 → compartment-4.1}/tests/test_ranking.py +0 -0
  77. {compartment-4 → compartment-4.1}/tests/test_relations.py +0 -0
  78. {compartment-4 → compartment-4.1}/tests/test_salience.py +0 -0
  79. {compartment-4 → compartment-4.1}/tests/test_session_entropy.py +0 -0
  80. {compartment-4 → compartment-4.1}/tests/test_session_lock.py +0 -0
  81. {compartment-4 → compartment-4.1}/tests/test_single_instance.py +0 -0
  82. {compartment-4 → compartment-4.1}/tests/test_starter_data_quality.py +0 -0
  83. {compartment-4 → compartment-4.1}/tests/test_starter_packs.py +0 -0
  84. {compartment-4 → compartment-4.1}/tests/test_starter_visibility.py +0 -0
  85. {compartment-4 → compartment-4.1}/tests/test_status_bar_install.py +0 -0
  86. {compartment-4 → compartment-4.1}/tests/test_systray.py +0 -0
  87. {compartment-4 → compartment-4.1}/tests/test_tamper.py +0 -0
  88. {compartment-4 → compartment-4.1}/tests/test_twofa.py +0 -0
  89. {compartment-4 → compartment-4.1}/tests/test_vault_ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: compartment
3
- Version: 4
3
+ Version: 4.1
4
4
  Summary: Compartment - high-security, fully offline, encrypted vector memory for AI agents (MCP)
5
5
  Project-URL: Homepage, https://github.com/MaxFreedomPollard/Compartment
6
6
  Project-URL: Source, https://github.com/MaxFreedomPollard/Compartment
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "compartment"
7
- version = "4"
7
+ version = "4.1"
8
8
  description = "Compartment - high-security, fully offline, encrypted vector memory for AI agents (MCP)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  """Compartment - high-security, fully offline, encrypted vector memory for AI agents."""
2
2
 
3
- __version__ = "4"
3
+ __version__ = "4.1"
4
4
 
5
5
  from . import offline_guard as _og
6
6
 
@@ -235,15 +235,24 @@ class Store:
235
235
  """Every embedding window, as (record ids, index keys, matrix).
236
236
 
237
237
  `ids` is parallel to `ikeys` and repeats: several windows of one long
238
- record each map back to the same record. A vault written before the
239
- `vecs` table existed has none, so it falls back to the single vector on
240
- each record, which is exactly what it used to search.
238
+ record each map back to the same record.
239
+
240
+ The two sources are UNIONED, never chosen between. A vault upgraded in
241
+ place is partial by construction - records written since the upgrade
242
+ carry window rows, every record written before it does not - so
243
+ "use `vecs` if it has any rows, otherwise use `records`" silently drops
244
+ every older memory out of the index. On a real vault that was 6,728 of
245
+ 6,839 memories, invisible to search while sitting safely in the file.
246
+ Each record contributes its windows if it has them and its original
247
+ single vector if it does not, and the two tables share one key space,
248
+ so nothing can collide.
241
249
  """
242
- rows = self.conn.execute(
243
- "SELECT id, ikey, vec FROM vecs ORDER BY ikey").fetchall()
244
- if not rows:
245
- rows = self.conn.execute(
246
- "SELECT id, ikey, vec FROM records ORDER BY ikey").fetchall()
250
+ rows = list(self.conn.execute(
251
+ "SELECT id, ikey, vec FROM vecs ORDER BY ikey").fetchall())
252
+ windowed = {r["id"] for r in rows}
253
+ rows += [r for r in self.conn.execute(
254
+ "SELECT id, ikey, vec FROM records ORDER BY ikey").fetchall()
255
+ if r["id"] not in windowed]
247
256
  ids = [r["id"] for r in rows]
248
257
  ikeys = [r["ikey"] for r in rows]
249
258
  if not rows:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: compartment
3
- Version: 4
3
+ Version: 4.1
4
4
  Summary: Compartment - high-security, fully offline, encrypted vector memory for AI agents (MCP)
5
5
  Project-URL: Homepage, https://github.com/MaxFreedomPollard/Compartment
6
6
  Project-URL: Source, https://github.com/MaxFreedomPollard/Compartment
@@ -154,3 +154,41 @@ def test_rebuild_windows_skips_short_records_without_tokenizing_them(vault):
154
154
  vault.store(f"A short memory number {i}.", caller="test",
155
155
  namespace="main")
156
156
  assert vault.rebuild_windows(caller="test")["examined"] == 0
157
+
158
+
159
+ # --------------------------------------------- upgrading an existing vault ---
160
+ def test_a_partly_upgraded_vault_indexes_every_record(vault):
161
+ """The regression that shipped in 4 and had to be fixed in 4.1.
162
+
163
+ A vault upgraded in place is PARTIAL: records written since the upgrade
164
+ carry window rows, everything written before does not. Choosing one table
165
+ over the other dropped every older memory out of the index while it sat
166
+ safely in the file - 6,728 of 6,839 on a real vault.
167
+ """
168
+ old = [vault.store(f"An older memory about topic {i}.", caller="test",
169
+ namespace="main")["id"] for i in range(5)]
170
+ vault.db.conn.execute("DELETE FROM vecs") # they predate windows
171
+ new = [vault.store(f"A newer memory about subject {i}.", caller="test",
172
+ namespace="main")["id"] for i in range(3)]
173
+ assert vault.db.conn.execute(
174
+ "SELECT count(DISTINCT id) c FROM vecs").fetchone()["c"] == 3
175
+
176
+ ids, ikeys, mat = vault.db.all_vectors()
177
+ assert set(old) | set(new) <= set(ids), "every record must reach the index"
178
+ assert len(ikeys) == len(set(ikeys)), "index keys must stay unique"
179
+ assert mat.shape[0] == len(ikeys)
180
+
181
+ vault._rebuild_index()
182
+ assert len(vault.index) == len(ikeys)
183
+ hits = vault.search("older memory about topic", caller="test", top_k=5)
184
+ assert any(h["id"] in old for h in hits["results"]), \
185
+ "a record written before the upgrade must still be findable"
186
+
187
+
188
+ def test_a_record_with_windows_is_not_also_indexed_by_its_head_vector(vault):
189
+ r = vault.store("long memory " * 400, caller="test", namespace="main")["id"]
190
+ ids, ikeys, _ = vault.db.all_vectors()
191
+ windows = vault.db.vector_keys(r)
192
+ assert len(windows) > 1
193
+ assert ids.count(r) == len(windows), \
194
+ "a windowed record contributes its windows and nothing else"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes