papez 0.6.0__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.
- papez-0.6.0/.dockerignore +19 -0
- papez-0.6.0/.env.example +48 -0
- papez-0.6.0/.gitignore +84 -0
- papez-0.6.0/.pre-commit-config.yaml +24 -0
- papez-0.6.0/CHANGELOG.md +65 -0
- papez-0.6.0/CLA.md +49 -0
- papez-0.6.0/CONTRIBUTING.md +89 -0
- papez-0.6.0/Dockerfile.mcp +10 -0
- papez-0.6.0/LICENSE +661 -0
- papez-0.6.0/PKG-INFO +317 -0
- papez-0.6.0/README.md +279 -0
- papez-0.6.0/SECURITY.md +16 -0
- papez-0.6.0/config/default_core_categories.json +20 -0
- papez-0.6.0/glama.json +6 -0
- papez-0.6.0/pyproject.toml +80 -0
- papez-0.6.0/server.json +43 -0
- papez-0.6.0/src/papez/__init__.py +18 -0
- papez-0.6.0/src/papez/__main__.py +14 -0
- papez-0.6.0/src/papez/context.py +9 -0
- papez-0.6.0/src/papez/core_memory/__init__.py +0 -0
- papez-0.6.0/src/papez/core_memory/preferences.py +60 -0
- papez-0.6.0/src/papez/core_memory/promoter.py +95 -0
- papez-0.6.0/src/papez/engine/__init__.py +0 -0
- papez-0.6.0/src/papez/engine/background.py +139 -0
- papez-0.6.0/src/papez/engine/config.py +301 -0
- papez-0.6.0/src/papez/engine/consolidation.py +64 -0
- papez-0.6.0/src/papez/engine/contradiction.py +152 -0
- papez-0.6.0/src/papez/engine/forgetting.py +35 -0
- papez-0.6.0/src/papez/engine/llm_provider.py +128 -0
- papez-0.6.0/src/papez/engine/reactivation.py +57 -0
- papez-0.6.0/src/papez/engine/scoring.py +104 -0
- papez-0.6.0/src/papez/engine/transitions.py +94 -0
- papez-0.6.0/src/papez/mcp/__init__.py +0 -0
- papez-0.6.0/src/papez/mcp/tools.py +1387 -0
- papez-0.6.0/src/papez/models/__init__.py +5 -0
- papez-0.6.0/src/papez/models/edge.py +23 -0
- papez-0.6.0/src/papez/models/enums.py +39 -0
- papez-0.6.0/src/papez/models/node.py +52 -0
- papez-0.6.0/src/papez/providers.py +111 -0
- papez-0.6.0/src/papez/retrieval/__init__.py +0 -0
- papez-0.6.0/src/papez/retrieval/date_anchor.py +199 -0
- papez-0.6.0/src/papez/retrieval/embedding.py +120 -0
- papez-0.6.0/src/papez/server.py +205 -0
- papez-0.6.0/src/papez/storage/__init__.py +0 -0
- papez-0.6.0/src/papez/storage/base.py +75 -0
- papez-0.6.0/src/papez/storage/cache.py +36 -0
- papez-0.6.0/src/papez/storage/memory.py +778 -0
- papez-0.6.0/tests/test_atomic_reactivation.py +97 -0
- papez-0.6.0/tests/test_benchmark.py +255 -0
- papez-0.6.0/tests/test_contradiction.py +115 -0
- papez-0.6.0/tests/test_core_memory.py +131 -0
- papez-0.6.0/tests/test_cross_org_security.py +141 -0
- papez-0.6.0/tests/test_e2e_core_operations.py +139 -0
- papez-0.6.0/tests/test_edge_semantics.py +346 -0
- papez-0.6.0/tests/test_edge_staleness.py +344 -0
- papez-0.6.0/tests/test_forgetting.py +97 -0
- papez-0.6.0/tests/test_gdpr_erasure.py +405 -0
- papez-0.6.0/tests/test_hybrid_retrieval.py +269 -0
- papez-0.6.0/tests/test_logging.py +76 -0
- papez-0.6.0/tests/test_mcp_tools.py +935 -0
- papez-0.6.0/tests/test_org_accounts.py +494 -0
- papez-0.6.0/tests/test_phase1_security.py +567 -0
- papez-0.6.0/tests/test_scoring.py +222 -0
- papez-0.6.0/tests/test_transitions.py +95 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
__pycache__
|
|
2
|
+
*.pyc
|
|
3
|
+
.git
|
|
4
|
+
.env
|
|
5
|
+
.venv
|
|
6
|
+
venv
|
|
7
|
+
node_modules
|
|
8
|
+
genesys-ui/node_modules
|
|
9
|
+
genesys-ui/.next
|
|
10
|
+
tests
|
|
11
|
+
benchmarks
|
|
12
|
+
phases
|
|
13
|
+
schemas
|
|
14
|
+
*.md
|
|
15
|
+
!README.md
|
|
16
|
+
.mypy_cache
|
|
17
|
+
.pytest_cache
|
|
18
|
+
.ruff_cache
|
|
19
|
+
docker-compose.yml
|
papez-0.6.0/.env.example
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Required: AI providers (OPENAI_API_KEY not needed when GENESYS_EMBEDDER=local)
|
|
2
|
+
OPENAI_API_KEY=sk-...
|
|
3
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
4
|
+
|
|
5
|
+
# Storage backend (this library ships the zero-dependency in-memory store)
|
|
6
|
+
GENESYS_BACKEND=memory
|
|
7
|
+
|
|
8
|
+
# Embedding provider: openai | local
|
|
9
|
+
# "openai" = OpenAI text-embedding-3-small (1536-dim, requires OPENAI_API_KEY)
|
|
10
|
+
# "local" = sentence-transformers all-MiniLM-L6-v2 (384-dim, no API key needed)
|
|
11
|
+
# pip install papez[local]
|
|
12
|
+
GENESYS_EMBEDDER=openai
|
|
13
|
+
|
|
14
|
+
# Persist path for in-memory backend (saves state across restarts)
|
|
15
|
+
# GENESYS_PERSIST_PATH=.genesys_state.json
|
|
16
|
+
|
|
17
|
+
# Default user ID (single-tenant / dev mode)
|
|
18
|
+
GENESYS_USER_ID=default_user
|
|
19
|
+
|
|
20
|
+
# Engine thresholds (all have sensible defaults — only override if tuning)
|
|
21
|
+
# See src/papez/engine/config.py for full list and documentation
|
|
22
|
+
# GENESYS_ACTR_DECAY=0.5 # ACT-R decay exponent (d parameter)
|
|
23
|
+
# GENESYS_RELEVANCE_VECTOR_WEIGHT=0.7 # Vector similarity weight in relevance
|
|
24
|
+
# GENESYS_RELEVANCE_KEYWORD_WEIGHT=0.3 # Keyword overlap weight in relevance
|
|
25
|
+
# GENESYS_MIN_CONNECTIVITY=0.1 # Floor for connectivity factor
|
|
26
|
+
# GENESYS_TAGGED_EXPIRE_HOURS=24 # Hours before orphan tagged nodes expire
|
|
27
|
+
# GENESYS_ACTIVE_EPISODIC_THRESHOLD=0.6 # Decay score below this increments counter
|
|
28
|
+
# GENESYS_ACTIVE_EPISODIC_SESSIONS=3 # Consecutive low-score sessions to downgrade
|
|
29
|
+
# GENESYS_DORMANCY_THRESHOLD=0.15 # Decay score threshold for dormancy
|
|
30
|
+
# GENESYS_DORMANCY_DAYS=90 # Days inactive before dormancy eligible
|
|
31
|
+
# GENESYS_DORMANCY_MAX_REACTIVATIONS=3 # Max reactivations allowed for dormancy
|
|
32
|
+
# GENESYS_FORGETTING_THRESHOLD=0.01 # Decay score floor for forgetting
|
|
33
|
+
# GENESYS_CORE_THRESHOLD=0.55 # Consolidation score for core promotion
|
|
34
|
+
# GENESYS_CORE_ACTIVATION_WEIGHT=0.4 # Activation weight in consolidation score
|
|
35
|
+
# GENESYS_CORE_HUB_WEIGHT=0.3 # Hub importance weight
|
|
36
|
+
# GENESYS_CORE_SCHEMA_WEIGHT=0.2 # Schema match weight
|
|
37
|
+
# GENESYS_CORE_STABILITY_WEIGHT=0.1 # Stability weight
|
|
38
|
+
# GENESYS_AUTO_PROMOTE_CATEGORIES=professional,educational,family,location
|
|
39
|
+
# GENESYS_RECALL_MIN_SIMILARITY= # Recall vector floor (default: embedder-recommended, OpenAI 0.5 / other 0.2)
|
|
40
|
+
# GENESYS_CORE_INJECT_MIN_SIMILARITY= # Core-injection floor (default: embedder-recommended, OpenAI 0.45 / other 0.2)
|
|
41
|
+
# GENESYS_AUTOLINK_MIN_SIMILARITY= # Auto-link floor (default: embedder-recommended, OpenAI 0.6 / other 0.45)
|
|
42
|
+
# GENESYS_AUTOLINK_MAX_EDGES=3 # Max auto-links per memory_store (fan-out cap)
|
|
43
|
+
# GENESYS_AUTOLINK_MAX_NODE_DEGREE=10 # Max auto_link edges a node may accumulate (hub cap)
|
|
44
|
+
# GENESYS_CONFLICT_MIN_SIMILARITY= # possible_conflicts scan floor (default: the recall floor)
|
|
45
|
+
# GENESYS_CONFLICT_SCAN_K=8 # possible_conflicts vector window
|
|
46
|
+
# GENESYS_CASCADE_DEPTH=2 # Max hops for spreading activation
|
|
47
|
+
# GENESYS_CASCADE_DECAY_FACTOR=0.3 # Decay per hop in cascade
|
|
48
|
+
# GENESYS_MAX_INGEST_FILE_MB=100 # Max file size for conversation imports
|
papez-0.6.0/.gitignore
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.pyo
|
|
5
|
+
*.egg-info/
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
.mypy_cache/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
|
|
14
|
+
# Node / Next.js
|
|
15
|
+
node_modules/
|
|
16
|
+
.next/
|
|
17
|
+
out/
|
|
18
|
+
.pnp.*
|
|
19
|
+
*.tsbuildinfo
|
|
20
|
+
|
|
21
|
+
# Environment
|
|
22
|
+
.env
|
|
23
|
+
.env.*
|
|
24
|
+
!.env.example
|
|
25
|
+
|
|
26
|
+
# OS
|
|
27
|
+
.DS_Store
|
|
28
|
+
|
|
29
|
+
# Benchmark logs
|
|
30
|
+
benchmarks/logs/
|
|
31
|
+
|
|
32
|
+
claude_desktop_config.json
|
|
33
|
+
|
|
34
|
+
# Project-specific exclusions
|
|
35
|
+
/ui/
|
|
36
|
+
/genesys-ui/
|
|
37
|
+
Dockerfile.ui
|
|
38
|
+
data/
|
|
39
|
+
|
|
40
|
+
# IDE
|
|
41
|
+
.idea/
|
|
42
|
+
.vscode/
|
|
43
|
+
|
|
44
|
+
# Benchmark data files (large datasets)
|
|
45
|
+
benchmarks/locomo10.json
|
|
46
|
+
benchmarks/locomo_eval_results.json
|
|
47
|
+
benchmarks/locomo_judged.json
|
|
48
|
+
benchmarks/.genesys_state*.json
|
|
49
|
+
|
|
50
|
+
# Internal docs (not for OSS)
|
|
51
|
+
phases/
|
|
52
|
+
schemas/
|
|
53
|
+
|
|
54
|
+
# Stitch design files
|
|
55
|
+
*.html
|
|
56
|
+
|
|
57
|
+
# Claude config
|
|
58
|
+
CLAUDE.md
|
|
59
|
+
|
|
60
|
+
# Internal notes
|
|
61
|
+
lessons.md
|
|
62
|
+
prompts/
|
|
63
|
+
|
|
64
|
+
# State snapshots
|
|
65
|
+
.genesys_state*.json
|
|
66
|
+
|
|
67
|
+
# Database migrations (production only)
|
|
68
|
+
alembic/
|
|
69
|
+
alembic.ini
|
|
70
|
+
|
|
71
|
+
# Handoff docs
|
|
72
|
+
genesys-neuro-handoff/
|
|
73
|
+
/local_storage/
|
|
74
|
+
|
|
75
|
+
# private / local / business — never publish
|
|
76
|
+
.claude/
|
|
77
|
+
.playwright-mcp/
|
|
78
|
+
.coverage
|
|
79
|
+
*.docx
|
|
80
|
+
/*.png
|
|
81
|
+
*AUDIT*.md
|
|
82
|
+
yc-*.md
|
|
83
|
+
PATENT_*.md
|
|
84
|
+
seed_*.py
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v4.6.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: check-yaml
|
|
6
|
+
- id: end-of-file-fixer
|
|
7
|
+
- id: trailing-whitespace
|
|
8
|
+
- id: check-added-large-files
|
|
9
|
+
args: ['--maxkb=1000']
|
|
10
|
+
|
|
11
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
12
|
+
rev: v0.4.8
|
|
13
|
+
hooks:
|
|
14
|
+
- id: ruff
|
|
15
|
+
args: [--fix]
|
|
16
|
+
|
|
17
|
+
- repo: local
|
|
18
|
+
hooks:
|
|
19
|
+
- id: no-hardcoded-secrets
|
|
20
|
+
name: Detect hardcoded secrets
|
|
21
|
+
language: pygrep
|
|
22
|
+
entry: '(sk_test_\w|sk_live_\w|sk-ant-api\w|AKIA[0-9A-Z]{16})'
|
|
23
|
+
types: [text]
|
|
24
|
+
exclude: '(\.env\.example|\.pre-commit-config\.yaml|CONTRIBUTING\.md)$'
|
papez-0.6.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
### Renamed: genesys-memory is now papez
|
|
6
|
+
|
|
7
|
+
- PyPI package `genesys-memory` -> `papez`; module `genesys_memory` -> `papez`; console script `genesys-memory` -> `papez`.
|
|
8
|
+
- The MCP server announces itself as `papez`. Update client configs: `claude mcp add papez -- python -m papez`.
|
|
9
|
+
- A final `genesys-memory` 0.6.0 release depends on `papez` and aliases every `genesys_memory.*` import to the same `papez.*` module, with a `DeprecationWarning`.
|
|
10
|
+
- Environment variables keep the `GENESYS_` prefix. Nothing about the data format changed.
|
|
11
|
+
|
|
12
|
+
## [0.4.2] - 2026-07-17
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **`memory_traverse` induced subgraph now includes the start node** and its incident edges. The in-memory provider returned the start node from `traverse()`; the Postgres provider excludes it (`WHERE id != start`), so on Postgres backends every edge incident to the start node was dropped from `edges` — including the sole match when `edge_types` filtered to a start-incident edge (e.g. traversing from an amended node with `edge_types=["supersedes"]` returned the right neighbor but zero edges). Normalized in the tool layer so all backends behave identically: the start node leads the node set and its edges appear.
|
|
17
|
+
|
|
18
|
+
## [0.4.1] - 2026-07-17
|
|
19
|
+
|
|
20
|
+
### Fixed (0.4.0 field-retest round 2)
|
|
21
|
+
|
|
22
|
+
- **Conflict-hint precision**: `possible_conflicts` numeric check now anchors numbers to the nearest *non-stopword* word and carries the number's unit (currency prefix, `%`, or following unit word). "latency is 200ms" no longer flags "budget is $50,000", and "6 weeks" vs "8 months" no longer collide; "budget $50,000" vs "budget $80,000" still fires.
|
|
23
|
+
- **Recall superseder down-ranking (latent)**: when the superseded memory fell outside the result set, recall marked the *superseding* memory as superseded and decayed it. SUPERSEDES is directed new→old; only targets are tagged now.
|
|
24
|
+
- **`memory_explain` edge direction**: edge entries gain a `direction` ("outgoing"/"incoming") field — an incoming `supersedes` edge previously read as if this node superseded the other. Legacy `target` (= other end) unchanged for compatibility.
|
|
25
|
+
- **Search/enumeration supersede visibility**: `memory_search` hits (both modes) now carry `superseded_by`, so change-cursor consumers can distinguish current from superseded memories without traversing edges.
|
|
26
|
+
|
|
27
|
+
## [0.4.0] - 2026-07-17
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- **`memory_amend` MCP tool** (tool count 12 → 13). Records a correction as a new memory that `SUPERSEDES` an existing one, reusing the `memory_store` hot path (embedding + auto-link + eventing). The old memory is intentionally kept — recall already decays superseded hits and tags them `superseded_by`, and the transitions engine demotes them naturally. Ownership-checked. Returns `{node_id, supersedes, status: "amended"}`.
|
|
32
|
+
- **Writer-specified typed edges** in `memory_store` via a new `related` argument: `[{"id", "type"}]`, directed `new_node --type--> target`, validated fail-fast (invalid edge types rejected before the node is created). Writers can now express `supersedes` / `contradicts` / `part_of` etc. instead of everything collapsing to `caused_by`. The legacy `related_to` argument is unchanged (still `caused_by`).
|
|
33
|
+
- **`category` argument** on `memory_store`, closing the half-wired category path (nodes carried a `category` field and `list_core_memories` filtered on it, but there was no way to set it). A caller-set category is never overwritten by the background LLM classifier.
|
|
34
|
+
- **Concise recall**: `memory_recall(verbosity="concise")` returns only `id/summary/status/score/activation/is_core` (plus `superseded_by` when set) and skips the expensive causal-chain enrichment. `verbosity="full"` remains the default and is unchanged. Reactivation writes still occur in both modes.
|
|
35
|
+
- **`activation` alias** for `decay_score` on every recall hit and in `memory_explain`, plus a `score_model` block in `memory_explain` (formula, live per-force `connectivity_factor`/`activation_factor`, and a `staleness_note`). Makes the score legible: it is an activation/retention weight that *rises* on retrieval, not a countdown to deletion. See `docs/scoring.md`.
|
|
36
|
+
- **`memory_traverse` now returns edges**: `edges` (`source/target/type/weight/created_by`) and `edge_count` for the induced subgraph among reachable nodes — a superset of the BFS tree, so paths can be reconstructed. Backed by a new `get_connecting_edges()` storage method (edge-type + org-visibility filtering done in storage; de-duped by edge id). The tool degrades gracefully when the provider does not implement `get_connecting_edges` (returns `edges: []`, `edge_count: 0` — same guard pattern as `get_causal_chains_batch`). **Parity note for genesys-server:** the postgres, falkordb, mongo, and obsidian providers do NOT yet implement `get_connecting_edges` and need it added to return traverse edges in production; until then production `memory_traverse` returns empty `edges`.
|
|
37
|
+
- **`active_since` filter** on `memory_search` (filters on `last_reactivated_at`), a sibling of the existing `since` (which filters `created_at`). Both accept tz-naive ISO dates (treated as UTC).
|
|
38
|
+
- **Enumeration mode on `memory_search`** ("what's new since I last looked"): an empty `query` skips vector search entirely and lists nodes by `last_reactivated_at` descending, honoring the same filters — works with no embedder configured, no seed query needed. Search hits (both modes) now also carry `last_reactivated_at` and `source_session` (additive fields) for provenance.
|
|
39
|
+
- **Embedder-aware auto-link tuning**: `GENESYS_AUTOLINK_MIN_SIMILARITY` (env override), `GENESYS_AUTOLINK_MAX_EDGES` (default 3, per-store fan-out cap), and `GENESYS_AUTOLINK_MAX_NODE_DEGREE` (default 10, per-node *accumulation* cap — a node that already carries that many `auto_link` edges accretes no more, so hubs stop growing one edge per store). The similarity floor resolves via `config.resolve_autolink_min_similarity()` — explicit env > embedder recommendation (OpenAI 0.6 / local 0.45) > 0.45 fallback — replacing the hardcoded 0.3. The non-OpenAI floor sits *above* the local genuine-match band top (~0.4) because MiniLM noise pairs were observed at ~0.44: under local embeddings only near-duplicate content auto-links. `recommended_autolink_min_similarity` added to the embedding providers.
|
|
40
|
+
- **`possible_conflicts` hint** on `memory_store`: a pure-stdlib `heuristic_conflict_signal` flags lexical numeric/negation divergence against vector-similar candidates. Advisory only — never materialized as `CONTRADICTS` edges. The conflict scan has its **own floor**, decoupled from the auto-link floor (`GENESYS_CONFLICT_MIN_SIMILARITY`, defaulting to the recall floor via `config.resolve_conflict_min_similarity()`) and a wider candidate window (`GENESYS_CONFLICT_SCAN_K`, default 8) — so raising the auto-link floor doesn't shrink conflict detection. `numeric_mismatch` only fires when differing numbers appear in a *comparable position* (same nearest-preceding context word, e.g. "costs 50" vs "costs 75"), not on any two texts that merely both contain numbers (dates vs IDs no longer trigger it).
|
|
41
|
+
- **Structured tool errors in the stdio server**: `call_tool` no longer propagates tool exceptions as protocol-level MCP failures. Missing required arguments and tool exceptions return a `{"error": ..., "retryable": bool}` payload; `retryable` is true only for read tools (`memory_recall`/`memory_search`/`memory_traverse`/`memory_explain`/`memory_stats`/`list_core_memories`), matching the README retry guidance (never blind-retry writes).
|
|
42
|
+
- `docs/scoring.md` — the scoring legibility doc (three forces, stability, status/pinning override, conjunctive forgetting, worked numbers).
|
|
43
|
+
- `SUPPORTIVE_EDGE_TYPES` and `NEGATIVE_EDGE_TYPES` enum sets in `models/enums.py` for explicit edge classification.
|
|
44
|
+
- `get_supportive_degree()` method on all storage providers (base protocol, in-memory, Postgres, FalkorDB, MongoDB, Obsidian).
|
|
45
|
+
- LLM reasoning is now captured in contradiction detection and causal inference edge metadata. The `reason` field from `detect_contradiction` and `infer_causal_edges` is persisted in the edge's `metadata` dict.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **Auto-link is less permissive (fixes the "hairball")**: higher, embedder-aware similarity floor plus a per-store fan-out cap (`AUTOLINK_MAX_EDGES`) keep traversal neighborhoods scoped. Auto-linking now de-dupes against *any* existing edge between a pair (any type, either direction), so a `user_explicit` `caused_by` is never shadowed by a parallel `auto_link related_to`.
|
|
50
|
+
- `memory_store`'s `summary` is generated by word-boundary truncation (`≤200` chars incl. ellipsis) so words are never split mid-token. Still truncation, not an LLM summary.
|
|
51
|
+
|
|
52
|
+
- **Edge semantics correctness (breaking behavior change):** Nodes with only `CONTRADICTS` or `SUPERSEDES` edges are now considered orphans for forgetting purposes. Previously, any edge — including contradiction edges — prevented a node from being classified as an orphan, which meant contradicted memories were immune to pruning and could be incorrectly promoted to core status.
|
|
53
|
+
|
|
54
|
+
- **Core promotion now uses supportive degree:** The hub score component of `consolidation_score()` now counts only supportive edges (`CAUSED_BY`, `SUPPORTS`, `DERIVED_FROM`, `RELATED_TO`), excluding `CONTRADICTS` and `SUPERSEDES`. Nodes whose connectivity comes entirely from contradiction edges will no longer be promoted to core. **Note for existing instances:** This change is forward-only. Nodes already promoted to CORE status are not re-evaluated automatically (`evaluate_core_promotion` skips CORE nodes). Existing CORE nodes promoted under the old rules stay CORE until manually demoted via `unpin_memory`. Production instances upgrading to this version should consider running a one-time backfill to re-evaluate CORE nodes under the stricter rules — specifically, any CORE node whose only edges are CONTRADICTS/SUPERSEDES may have been mis-promoted.
|
|
55
|
+
|
|
56
|
+
- **Superseded nodes deprioritized in retrieval:** Nodes with incoming `SUPERSEDES` edges now receive a 0.3x multiplier on their retrieval rank score. They still appear in results (for audit trail purposes) but are ranked lower than their replacements.
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- **Positional backward compatibility of `memory_store`**: the new `related` and `category` parameters are appended *after* the original positional tail (`created_at`, `visibility`, `org_id`), not inserted mid-signature — existing positional callers of the published API keep working.
|
|
61
|
+
- `memory_search`'s `since`/`active_since` filters no longer raise `TypeError` on tz-naive ISO input (e.g. `"2050-01-01"`); naive timestamps are normalized to UTC, same as `memory_store`'s `created_at`.
|
|
62
|
+
- `is_orphan()` across all storage providers now uses supportive degree instead of raw degree. A node with only negative edges (contradictions, supersessions) is correctly identified as an orphan.
|
|
63
|
+
- `get_orphans()` updated to match new orphan semantics across all providers.
|
|
64
|
+
- Contradiction reasoning was being requested from the LLM but discarded at parse time. Now captured and stored.
|
|
65
|
+
- Causal inference prompt now requests reasoning; previously only asked for target, type, and confidence.
|
papez-0.6.0/CLA.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Papez Contributor License Agreement
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Papez, owned and maintained by Astrix Labs ("Company"). This Contributor License Agreement ("Agreement") is a legal document that clarifies the intellectual property rights granted with contributions from any person or entity ("Contributor") to the Company for the Papez project.
|
|
4
|
+
|
|
5
|
+
By submitting a pull request or otherwise contributing to the Papez project, you accept and agree to the following terms and conditions.
|
|
6
|
+
|
|
7
|
+
## 1. Definitions
|
|
8
|
+
|
|
9
|
+
**"Contribution"** means any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by the Contributor to the Company for inclusion in the Papez project. "Submitted" means any form of electronic, verbal, or written communication sent to the Company or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Company, but excluding communication that is conspicuously marked or otherwise designated in writing by the Contributor as "Not a Contribution."
|
|
10
|
+
|
|
11
|
+
**"Copyright"** means all rights protecting works of authorship, including copyright, moral, and neighboring rights, as appropriate, for the full term of their existence.
|
|
12
|
+
|
|
13
|
+
## 2. Grant of Copyright License
|
|
14
|
+
|
|
15
|
+
Subject to the terms and conditions of this Agreement, the Contributor hereby grants to the Company a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Contributions and such derivative works.
|
|
16
|
+
|
|
17
|
+
## 3. Grant of Patent License
|
|
18
|
+
|
|
19
|
+
Subject to the terms and conditions of this Agreement, the Contributor hereby grants to the Company a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer Contributions, where such license applies only to those patent claims licensable by the Contributor that are necessarily infringed by the Contribution alone or by combination of the Contribution with the project to which the Contribution was submitted.
|
|
20
|
+
|
|
21
|
+
## 4. Right to Grant Licenses
|
|
22
|
+
|
|
23
|
+
The Contributor represents that they are legally entitled to grant the above licenses. If the Contributor's employer(s) has rights to intellectual property that the Contributor creates, the Contributor represents that they have received permission to make Contributions on behalf of that employer, or that the employer has waived such rights for Contributions to the Papez project.
|
|
24
|
+
|
|
25
|
+
## 5. Original Work
|
|
26
|
+
|
|
27
|
+
The Contributor represents that each Contribution is the Contributor's original creation. The Contributor represents that Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which the Contributor is aware and which are associated with any part of the Contributions.
|
|
28
|
+
|
|
29
|
+
## 6. No Support Obligation
|
|
30
|
+
|
|
31
|
+
The Contributor is not expected to provide support for Contributions, except to the extent the Contributor desires to provide support. Support, if any, is provided on a voluntary basis.
|
|
32
|
+
|
|
33
|
+
## 7. Relicensing Rights
|
|
34
|
+
|
|
35
|
+
The Contributor acknowledges and agrees that the Company may, at its sole discretion, relicense the Papez project (including the Contributor's Contributions) under different license terms, including but not limited to commercial or proprietary licenses. This right is necessary for the Company to offer dual-licensed commercial deployments of Papez.
|
|
36
|
+
|
|
37
|
+
## 8. Notification
|
|
38
|
+
|
|
39
|
+
The Contributor agrees to notify the Company of any facts or circumstances of which the Contributor becomes aware that would make these representations inaccurate in any respect.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## How to Sign
|
|
44
|
+
|
|
45
|
+
By opening a pull request against the Papez repository, you acknowledge that you have read this Agreement and agree to its terms. Your git commit metadata (name and email address) serves as your electronic signature.
|
|
46
|
+
|
|
47
|
+
If you are contributing on behalf of a company or organization, please have an authorized representative email cla@astrixlabs.ai with the subject "Corporate CLA — [Company Name]" to sign a corporate version of this agreement.
|
|
48
|
+
|
|
49
|
+
For questions, contact: cla@astrixlabs.ai
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Contributing to Papez
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! Papez is open source under the [GNU Affero General Public License v3.0](LICENSE).
|
|
4
|
+
|
|
5
|
+
## Contributor License Agreement
|
|
6
|
+
|
|
7
|
+
All contributors must agree to our [Contributor License Agreement](CLA.md) before their code can be merged. By opening a pull request, you acknowledge that you have read the CLA and agree to its terms. Your git commit metadata (name and email) serves as your electronic signature.
|
|
8
|
+
|
|
9
|
+
The CLA grants Astrix Labs the right to include your contributions under the project's license (AGPLv3) and, where necessary, under commercial license terms for the hosted Papez service. You retain copyright over your contributions.
|
|
10
|
+
|
|
11
|
+
## Architecture overview
|
|
12
|
+
|
|
13
|
+
Papez is a scoring engine, causal graph, and lifecycle manager for AI memory. The codebase is organized as:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/papez/
|
|
17
|
+
├── engine/ # Scoring, transitions, forgetting, reactivation
|
|
18
|
+
│ ├── config.py # All tunable thresholds (env-configurable)
|
|
19
|
+
│ ├── scoring.py # Three-force multiplicative decay scoring
|
|
20
|
+
│ ├── transitions.py # Status FSM (TAGGED -> ACTIVE -> EPISODIC -> DORMANT)
|
|
21
|
+
│ ├── forgetting.py # Conjunctive active forgetting
|
|
22
|
+
│ └── reactivation.py # BFS cascade reactivation
|
|
23
|
+
├── core_memory/ # Core promotion logic (graph-derived)
|
|
24
|
+
├── storage/ # Storage provider abstractions + in-memory implementation
|
|
25
|
+
│ ├── base.py # Abstract interfaces (GraphStorageProvider, etc.)
|
|
26
|
+
│ └── memory.py # In-memory (zero deps)
|
|
27
|
+
├── retrieval/ # Embedding providers (OpenAI, local sentence-transformers)
|
|
28
|
+
├── mcp/ # MCP tool definitions
|
|
29
|
+
├── server.py # Lightweight stdio MCP server
|
|
30
|
+
└── providers.py # Provider wiring (in-memory backend, optional embeddings)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Key design principles:
|
|
34
|
+
- **Storage abstraction is mandatory.** All data access goes through provider interfaces in `storage/base.py`. Never import a database client directly in business logic.
|
|
35
|
+
- **Background processing for heavy operations.** Embedding generation, entity extraction, LLM-based inference, and consolidation are all async background tasks.
|
|
36
|
+
- **The scoring formula is sacred.** `decay_score = relevance x connectivity x reactivation`. Multiplicative — zero on any axis means zero total.
|
|
37
|
+
|
|
38
|
+
## Getting started
|
|
39
|
+
|
|
40
|
+
1. Fork the repo and clone it
|
|
41
|
+
2. Install dependencies: `pip install -e ".[dev]"`
|
|
42
|
+
3. Run tests: `pytest`
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Run the lightweight MCP server (stdio transport, no infrastructure needed)
|
|
46
|
+
python -m papez
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Code style
|
|
50
|
+
|
|
51
|
+
- **Python 3.11+**, async-first
|
|
52
|
+
- **Linting**: `ruff check src/` (config in `pyproject.toml`, line length 120)
|
|
53
|
+
- **Type checking**: `mypy src/papez --ignore-missing-imports` (strict mode configured)
|
|
54
|
+
- **Formatting**: follow existing patterns — type hints throughout, minimal comments
|
|
55
|
+
- Engine thresholds live in `engine/config.py` and are env-configurable. Don't hardcode magic numbers in engine files.
|
|
56
|
+
|
|
57
|
+
## Testing
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Run all unit tests
|
|
61
|
+
pytest tests/ -v
|
|
62
|
+
|
|
63
|
+
# With coverage
|
|
64
|
+
pytest tests/ -v --cov=src/papez --cov-report=term-missing
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Tests are in `tests/` and use `pytest-asyncio` (auto mode). When adding new engine logic, add corresponding test cases in the relevant test file.
|
|
68
|
+
|
|
69
|
+
## Pull requests
|
|
70
|
+
|
|
71
|
+
- Keep PRs focused — one feature or fix per PR
|
|
72
|
+
- Add tests for new functionality
|
|
73
|
+
- Make sure `pytest` and `ruff check src/` pass before submitting
|
|
74
|
+
- If your change touches engine logic (scoring, transitions, forgetting, promotion), run the full test suite — these modules are tightly coupled
|
|
75
|
+
|
|
76
|
+
## Reporting issues
|
|
77
|
+
|
|
78
|
+
Open an issue on GitHub with:
|
|
79
|
+
- Steps to reproduce
|
|
80
|
+
- Python version and backend
|
|
81
|
+
- Relevant error output or logs
|
|
82
|
+
|
|
83
|
+
## Good first issues
|
|
84
|
+
|
|
85
|
+
Look for issues labeled [`good first issue`](https://github.com/Astrix-Labs/papez/labels/good%20first%20issue). These are scoped, well-defined tasks suitable for new contributors.
|
|
86
|
+
|
|
87
|
+
## Code of conduct
|
|
88
|
+
|
|
89
|
+
Be kind. We're all here to build something useful.
|