loki-mode 7.7.27 → 7.7.29

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.
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.7.27'
60
+ __version__ = '7.7.29'
@@ -1558,6 +1558,35 @@ class MemoryRetrieval:
1558
1558
  if self._belongs_to_namespace(anti_copy):
1559
1559
  results.append(anti_copy)
1560
1560
 
1561
+ # Consolidation writes anti-patterns as SemanticPattern objects with
1562
+ # category="anti-pattern" into semantic/patterns.json (not the legacy
1563
+ # anti-patterns.json above), with fields incorrect_approach /
1564
+ # description / correct_approach. Without this bridge, consolidated
1565
+ # anti-patterns were never retrievable. Map them onto the same
1566
+ # what_fails / why / prevention scoring shape.
1567
+ patterns_data = self.storage.read_json("semantic/patterns.json") or {}
1568
+ for pat in patterns_data.get("patterns", []):
1569
+ if pat.get("category") != "anti-pattern":
1570
+ continue
1571
+ what_fails = (pat.get("incorrect_approach", "")
1572
+ or pat.get("pattern", "")).lower()
1573
+ why = pat.get("description", "").lower()
1574
+ prevention = pat.get("correct_approach", "").lower()
1575
+
1576
+ score = sum(2 for kw in keywords if kw in what_fails)
1577
+ score += sum(1 for kw in keywords if kw in why)
1578
+ score += sum(1 for kw in keywords if kw in prevention)
1579
+
1580
+ if score > 0:
1581
+ anti_copy = dict(pat)
1582
+ anti_copy["_score"] = score
1583
+ anti_copy["_source"] = "anti_patterns"
1584
+ anti_copy.setdefault("what_fails", pat.get("incorrect_approach", "") or pat.get("pattern", ""))
1585
+ anti_copy.setdefault("why", pat.get("description", ""))
1586
+ anti_copy.setdefault("prevention", pat.get("correct_approach", ""))
1587
+ if self._belongs_to_namespace(anti_copy):
1588
+ results.append(anti_copy)
1589
+
1561
1590
  return results
1562
1591
 
1563
1592
  def _build_episodic_index(self) -> None:
@@ -1654,3 +1683,23 @@ class MemoryRetrieval:
1654
1683
  # Add to index with ID
1655
1684
  item_id = anti.get("id", anti.get("source", f"anti-{hash(text) % 10000}"))
1656
1685
  index.add(item_id, embedding, anti)
1686
+
1687
+ # Parity with the keyword path: consolidation writes anti-patterns as
1688
+ # category="anti-pattern" entries in semantic/patterns.json, not the
1689
+ # legacy anti-patterns.json above. Bridge those into the vector index
1690
+ # too so embedding-based retrieval sees consolidated anti-patterns.
1691
+ patterns_data = self.storage.read_json("semantic/patterns.json") or {}
1692
+ for pat in patterns_data.get("patterns", []):
1693
+ if pat.get("category") != "anti-pattern":
1694
+ continue
1695
+ what_fails = pat.get("incorrect_approach", "") or pat.get("pattern", "")
1696
+ why = pat.get("description", "")
1697
+ prevention = pat.get("correct_approach", "")
1698
+ text = f"{what_fails} {why} {prevention}"
1699
+ embedding = self.embedding_engine.embed(text)
1700
+ item_id = pat.get("id", f"anti-{hash(text) % 10000}")
1701
+ bridged = dict(pat)
1702
+ bridged.setdefault("what_fails", what_fails)
1703
+ bridged.setdefault("why", why)
1704
+ bridged.setdefault("prevention", prevention)
1705
+ index.add(item_id, embedding, bridged)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "7.7.27",
3
+ "version": "7.7.29",
4
4
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 11 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
5
5
  "keywords": [
6
6
  "agent",