memgit 0.8.0__tar.gz → 0.8.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 (53) hide show
  1. {memgit-0.8.0 → memgit-0.8.1}/PKG-INFO +1 -1
  2. {memgit-0.8.0 → memgit-0.8.1}/memgit/__init__.py +1 -1
  3. {memgit-0.8.0 → memgit-0.8.1}/memgit/delivery.py +32 -0
  4. {memgit-0.8.0 → memgit-0.8.1}/memgit.egg-info/PKG-INFO +1 -1
  5. {memgit-0.8.0 → memgit-0.8.1}/pyproject.toml +1 -1
  6. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v081.py +26 -0
  7. {memgit-0.8.0 → memgit-0.8.1}/LICENSE +0 -0
  8. {memgit-0.8.0 → memgit-0.8.1}/README.md +0 -0
  9. {memgit-0.8.0 → memgit-0.8.1}/memgit/cli.py +0 -0
  10. {memgit-0.8.0 → memgit-0.8.1}/memgit/cloud/__init__.py +0 -0
  11. {memgit-0.8.0 → memgit-0.8.1}/memgit/cloud/client.py +0 -0
  12. {memgit-0.8.0 → memgit-0.8.1}/memgit/cloud/commands.py +0 -0
  13. {memgit-0.8.0 → memgit-0.8.1}/memgit/cloud/crypto.py +0 -0
  14. {memgit-0.8.0 → memgit-0.8.1}/memgit/cloud/state.py +0 -0
  15. {memgit-0.8.0 → memgit-0.8.1}/memgit/cloud/sync.py +0 -0
  16. {memgit-0.8.0 → memgit-0.8.1}/memgit/evaluate.py +0 -0
  17. {memgit-0.8.0 → memgit-0.8.1}/memgit/gitdigest.py +0 -0
  18. {memgit-0.8.0 → memgit-0.8.1}/memgit/graph.py +0 -0
  19. {memgit-0.8.0 → memgit-0.8.1}/memgit/hooks.py +0 -0
  20. {memgit-0.8.0 → memgit-0.8.1}/memgit/http_server.py +0 -0
  21. {memgit-0.8.0 → memgit-0.8.1}/memgit/importer.py +0 -0
  22. {memgit-0.8.0 → memgit-0.8.1}/memgit/links.py +0 -0
  23. {memgit-0.8.0 → memgit-0.8.1}/memgit/mcp_server.py +0 -0
  24. {memgit-0.8.0 → memgit-0.8.1}/memgit/metrics.py +0 -0
  25. {memgit-0.8.0 → memgit-0.8.1}/memgit/models.py +0 -0
  26. {memgit-0.8.0 → memgit-0.8.1}/memgit/project.py +0 -0
  27. {memgit-0.8.0 → memgit-0.8.1}/memgit/repo.py +0 -0
  28. {memgit-0.8.0 → memgit-0.8.1}/memgit/sanitize.py +0 -0
  29. {memgit-0.8.0 → memgit-0.8.1}/memgit/scorer.py +0 -0
  30. {memgit-0.8.0 → memgit-0.8.1}/memgit/store.py +0 -0
  31. {memgit-0.8.0 → memgit-0.8.1}/memgit/tokens.py +0 -0
  32. {memgit-0.8.0 → memgit-0.8.1}/memgit/toon.py +0 -0
  33. {memgit-0.8.0 → memgit-0.8.1}/memgit/usage.py +0 -0
  34. {memgit-0.8.0 → memgit-0.8.1}/memgit.egg-info/SOURCES.txt +0 -0
  35. {memgit-0.8.0 → memgit-0.8.1}/memgit.egg-info/dependency_links.txt +0 -0
  36. {memgit-0.8.0 → memgit-0.8.1}/memgit.egg-info/entry_points.txt +0 -0
  37. {memgit-0.8.0 → memgit-0.8.1}/memgit.egg-info/requires.txt +0 -0
  38. {memgit-0.8.0 → memgit-0.8.1}/memgit.egg-info/top_level.txt +0 -0
  39. {memgit-0.8.0 → memgit-0.8.1}/setup.cfg +0 -0
  40. {memgit-0.8.0 → memgit-0.8.1}/tests/test_accrue.py +0 -0
  41. {memgit-0.8.0 → memgit-0.8.1}/tests/test_advanced.py +0 -0
  42. {memgit-0.8.0 → memgit-0.8.1}/tests/test_aliases.py +0 -0
  43. {memgit-0.8.0 → memgit-0.8.1}/tests/test_core.py +0 -0
  44. {memgit-0.8.0 → memgit-0.8.1}/tests/test_delivery.py +0 -0
  45. {memgit-0.8.0 → memgit-0.8.1}/tests/test_setup.py +0 -0
  46. {memgit-0.8.0 → memgit-0.8.1}/tests/test_store_repo.py +0 -0
  47. {memgit-0.8.0 → memgit-0.8.1}/tests/test_toon.py +0 -0
  48. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v020.py +0 -0
  49. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v030.py +0 -0
  50. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v040.py +0 -0
  51. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v060.py +0 -0
  52. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v070.py +0 -0
  53. {memgit-0.8.0 → memgit-0.8.1}/tests/test_v080.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memgit
3
- Version: 0.8.0
3
+ Version: 0.8.1
4
4
  Summary: Git for AI memory — version-controlled context persistence across Claude, GPT, Gemini, Cursor, Windsurf, and more
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://memgit.dev
@@ -1,3 +1,3 @@
1
1
  """memgit — git for AI memory."""
2
2
 
3
- __version__ = "0.8.0"
3
+ __version__ = "0.8.1"
@@ -229,6 +229,37 @@ def collect_skills(root: Path, home: Optional[Path] = None) -> list[tuple[str, s
229
229
  return sorted(found.items())
230
230
 
231
231
 
232
+ #: Per-skill budget in the guide's routing list. The guide is injected every
233
+ #: session on every host, so it is the single most expensive surface memgit
234
+ #: owns — and a 2026-08-05 audit measured it as the LOWEST-yield memory type
235
+ #: (2.10 recalls/memory vs 17.5 for feedback). Skill `description` frontmatter
236
+ #: is written to persuade a model to invoke the skill and routinely runs 600+
237
+ #: chars; on a store with 18 skills that was 6,968 of the guide's 9,425 chars.
238
+ #: The guide only needs to answer "which skill covers this?" — the full text
239
+ #: is in the skill itself, one Read away.
240
+ _SKILL_DESC_MAX = 150
241
+
242
+
243
+ def _routing_summary(desc: str) -> str:
244
+ """Trim a skill description to the part that answers 'is this the one?'.
245
+
246
+ Prefers a clean sentence break inside the budget; falls back to a word
247
+ boundary. Never mid-word, and never a bare ellipsis with no content.
248
+ """
249
+ desc = ' '.join((desc or '').split())
250
+ if len(desc) <= _SKILL_DESC_MAX:
251
+ return desc
252
+ window = desc[:_SKILL_DESC_MAX + 1]
253
+ for stop in ('. ', '; ', ' — ', ' - '):
254
+ cut = window.rfind(stop)
255
+ if cut >= _SKILL_DESC_MAX // 2:
256
+ return desc[:cut].rstrip(' .;—-') + '.'
257
+ cut = window.rfind(' ')
258
+ if cut < _SKILL_DESC_MAX // 2:
259
+ cut = _SKILL_DESC_MAX
260
+ return desc[:cut].rstrip(' .;,—-') + '…'
261
+
262
+
232
263
  def _store_scale(repo, project: Optional[str]) -> Optional[tuple[int, list[str]]]:
233
264
  """(memory count, top topic tags) for this project — the concrete evidence
234
265
  the guide leads with. Returns None when there is nothing worth stating."""
@@ -298,6 +329,7 @@ def build_seed(root: Path, home: Optional[Path] = None,
298
329
  if skills:
299
330
  lines += ["", "## Available skills (invoke by name when the task matches)"]
300
331
  for name, desc in skills:
332
+ desc = _routing_summary(desc)
301
333
  lines.append(f"- **{name}** — {desc}" if desc else f"- **{name}**")
302
334
 
303
335
  rule_files = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memgit
3
- Version: 0.8.0
3
+ Version: 0.8.1
4
4
  Summary: Git for AI memory — version-controlled context persistence across Claude, GPT, Gemini, Cursor, Windsurf, and more
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://memgit.dev
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memgit"
7
- version = "0.8.0"
7
+ version = "0.8.1"
8
8
  description = "Git for AI memory — version-controlled context persistence across Claude, GPT, Gemini, Cursor, Windsurf, and more"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -368,6 +368,32 @@ class TestSeedEvidence:
368
368
  assert "**9 saved memories**" in body
369
369
  assert "crypto" in body
370
370
 
371
+ def test_long_skill_descriptions_are_trimmed(self, tmp_path):
372
+ """The guide is injected every session on every host; skill frontmatter
373
+ is written to persuade and runs long. Routing needs a sentence."""
374
+ from memgit.delivery import build_seed, _SKILL_DESC_MAX
375
+ skills = tmp_path / ".claude" / "skills" / "verbose"
376
+ skills.mkdir(parents=True)
377
+ long_desc = ("Mandatory entry point: read this first for any request. "
378
+ + "Additional qualifying detail. " * 30)
379
+ (skills / "SKILL.md").write_text(
380
+ f"---\nname: verbose\ndescription: {long_desc}\n---\nbody\n")
381
+ body = build_seed(tmp_path, home=tmp_path)
382
+ line = next(l for l in body.splitlines() if l.startswith("- **verbose**"))
383
+ assert len(line) < _SKILL_DESC_MAX + 40
384
+ assert "Mandatory entry point" in line, "the routing signal must survive"
385
+
386
+ def test_short_descriptions_untouched(self, tmp_path):
387
+ from memgit.delivery import _routing_summary
388
+ d = "Deploy the portfolio to Vercel."
389
+ assert _routing_summary(d) == d
390
+
391
+ def test_trim_never_cuts_mid_word(self, tmp_path):
392
+ from memgit.delivery import _routing_summary
393
+ out = _routing_summary("alpha " * 100)
394
+ assert not out.rstrip("…").endswith("alph")
395
+ assert out.endswith(("…", ".")) and len(out.strip("…. ")) > 20
396
+
371
397
  def test_seed_stays_quiet_below_the_bar(self, tmp_path):
372
398
  from memgit.delivery import build_seed
373
399
 
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
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
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
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes