luminary-memory 0.3.0__tar.gz → 0.3.2__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.
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/workflows/ci.yml +28 -1
- luminary_memory-0.3.2/.github/workflows/publish.yml +191 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.gitignore +6 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/CHANGELOG.md +109 -0
- luminary_memory-0.3.2/CONTRIBUTING.md +281 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/PKG-INFO +52 -1
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/README.md +51 -0
- luminary_memory-0.3.2/benchmarks/README.md +160 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/RESULTS.md +4 -0
- luminary_memory-0.3.2/benchmarks/baselines/README.md +44 -0
- luminary_memory-0.3.2/benchmarks/baselines/gold-real-v1.json +196 -0
- luminary_memory-0.3.2/benchmarks/baselines/gold-real-v2.json +189 -0
- luminary_memory-0.3.2/benchmarks/build_gold_extended.py +167 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/gold.py +42 -0
- luminary_memory-0.3.2/benchmarks/gold_extended.jsonl +44 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/run_benchmarks.py +73 -6
- luminary_memory-0.3.2/docs/agent-integrations.md +292 -0
- luminary_memory-0.3.2/package-lock.json +4489 -0
- luminary_memory-0.3.2/package.json +19 -0
- luminary_memory-0.3.2/plugins/omp/README.md +130 -0
- luminary_memory-0.3.2/plugins/omp/package.json +47 -0
- luminary_memory-0.3.2/plugins/opencode/README.md +118 -0
- luminary_memory-0.3.2/plugins/opencode/package.json +30 -0
- luminary_memory-0.3.2/plugins/pi/README.md +136 -0
- luminary_memory-0.3.2/plugins/pi/package.json +59 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/pyproject.toml +1 -1
- luminary_memory-0.3.2/scripts/build-plugins.mjs +68 -0
- luminary_memory-0.3.2/scripts/bump-version.sh +124 -0
- luminary_memory-0.3.2/scripts/pack-plugins.mjs +33 -0
- luminary_memory-0.3.2/scripts/smoke-real-model.py +198 -0
- luminary_memory-0.3.2/scripts/soak-test.py +253 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/__init__.py +1 -1
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/api.py +8 -5
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/cli.py +2 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/config.py +24 -1
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/hermes/plugin.yaml +2 -2
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/ingest/llm.py +132 -96
- luminary_memory-0.3.2/src/luminary_memory/integrations/__init__.py +233 -0
- luminary_memory-0.3.2/src/luminary_memory/integrations/__main__.py +6 -0
- luminary_memory-0.3.2/src/luminary_memory/integrations/assets/omp/luminary.ts +172 -0
- luminary_memory-0.3.2/src/luminary_memory/integrations/assets/opencode/luminary-memory.ts +323 -0
- luminary_memory-0.3.2/src/luminary_memory/integrations/assets/opencode/package.json +7 -0
- luminary_memory-0.3.2/src/luminary_memory/integrations/assets/pi/luminary.ts +173 -0
- luminary_memory-0.3.2/src/luminary_memory/integrations/cli.py +130 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/semantic.py +6 -2
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_provider_import.py +20 -0
- luminary_memory-0.3.2/tests/plugins/packages.test.mjs +137 -0
- luminary_memory-0.3.2/tests/test_agent_integrations.py +160 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_backend_sqlite.py +49 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_budget.py +8 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_dedup_jaccard.py +7 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_embeddings.py +6 -0
- luminary_memory-0.3.2/tests/test_gold_benchmark.py +136 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_importance.py +18 -0
- luminary_memory-0.3.2/tests/test_ingest_whitelist.py +56 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_llm_enricher.py +60 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_recall_keyword.py +11 -0
- luminary_memory-0.3.2/tests/test_soak_behaviour.py +130 -0
- luminary_memory-0.3.2/tests/test_strict_recall_calibration.py +132 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t3_planner.py +20 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t8_snippets.py +6 -0
- luminary_memory-0.3.2/tests/test_validity_window.py +132 -0
- luminary_memory-0.3.2/website/css/docs.css +1364 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/website/css/luminary.css +60 -17
- luminary_memory-0.3.2/website/docs.html +124 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/website/index.html +2 -2
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/website/js/docs-content.js +11 -1
- luminary_memory-0.3.2/website/js/docs-guides.js +988 -0
- luminary_memory-0.3.2/website/js/docs-page.js +393 -0
- luminary_memory-0.3.0/.github/workflows/publish.yml +0 -46
- luminary_memory-0.3.0/CONTRIBUTING.md +0 -120
- luminary_memory-0.3.0/benchmarks/README.md +0 -66
- luminary_memory-0.3.0/scripts/bump-version.sh +0 -75
- luminary_memory-0.3.0/tests/test_ingest_whitelist.py +0 -31
- luminary_memory-0.3.0/website/css/docs.css +0 -475
- luminary_memory-0.3.0/website/docs.html +0 -83
- luminary_memory-0.3.0/website/js/docs-guides.js +0 -147
- luminary_memory-0.3.0/website/js/docs-page.js +0 -131
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/workflows/contributor-check.yml +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/workflows/pages.yml +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/workflows/stale.yml +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/.github/workflows/triage.yml +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/CODE_OF_CONDUCT.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/DESIGN.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/LICENSE +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/PRODUCT.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/SECURITY.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/gold_micro.jsonl +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/hermes_provider_bench.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/metrics.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/benchmarks/synthetic.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/README.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/SKILL.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/hooks/luminary-activity/HOOK.yaml +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/hooks/luminary-activity/README.md +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/hooks/luminary-activity/handler.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/install.sh +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/hermes/test.sh +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/scripts/repair_memory_authority.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/backends/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/backends/base.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/backends/pgvector.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/backends/sqlite.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/budget.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/embeddings/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/embeddings/fastembed.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/export.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/hermes/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/hermes/activation.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/hermes/config.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/hermes/config_schema.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/hermes/provider.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/ingest/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/ingest/rules.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/ingest/whitelist.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/lifecycle/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/lifecycle/cleanup.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/lifecycle/consolidate.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/lifecycle/importance.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/lifecycle/prune.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/lifecycle/runner.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/dedup.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/fusion.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/graph.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/keyword.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/planner.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/snippets.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/recall/temporal.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/schema.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/scope.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/src/luminary_memory/types.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/__init__.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/conftest.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_activation.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_activity_hook.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_authority_lifecycle.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_autonomous_review.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_backup_paths.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_config.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_context_continuity.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_core_memory.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_entrypoint.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_hooks.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_lifecycle.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_long_term_stability.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_pre_compress.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_provider_context.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_recall.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_recall_smartness.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_session_boundaries.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_sync_turn.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_system_prompt.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_tools.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes/test_transparency_log.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/hermes_stubs/agent/memory_provider.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_accuracy_safety.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_api.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_api_extended.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_backend_pgvector.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_cli.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_fusion.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_fusion_rrf.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_ingest_llm.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_lifecycle.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_long_term_stability.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_memory_authority_migration.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_query_expansion.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_recall_adaptive.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_recall_graph.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_recall_orchestrator.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_recall_semantic.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_recall_temporal.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_schema.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_scope_boundaries.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t10_export.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t11_limit_zero.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t1_hnsw.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t4_batch.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t5_enricher.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t6_tag_scoped.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t7_updated_at.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/tests/test_t9_cli_json.py +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/website/.nojekyll +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/website/assets/full-moon.jpg +0 -0
- {luminary_memory-0.3.0 → luminary_memory-0.3.2}/website/js/luminary.js +0 -0
|
@@ -24,7 +24,34 @@ jobs:
|
|
|
24
24
|
- name: Test and coverage
|
|
25
25
|
run: |
|
|
26
26
|
python -m coverage run --source=src/luminary_memory -m pytest -q
|
|
27
|
-
python -m coverage report --fail-under=
|
|
27
|
+
python -m coverage report --fail-under=82
|
|
28
|
+
|
|
29
|
+
native-packages:
|
|
30
|
+
name: Native plugin packages
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v4
|
|
34
|
+
- uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.11"
|
|
37
|
+
cache: pip
|
|
38
|
+
- name: Install the actual Python bridge
|
|
39
|
+
run: python -m pip install -e ".[dev]"
|
|
40
|
+
- uses: actions/setup-node@v4
|
|
41
|
+
with:
|
|
42
|
+
node-version: "22"
|
|
43
|
+
check-latest: true
|
|
44
|
+
cache: npm
|
|
45
|
+
- run: npm ci --ignore-scripts
|
|
46
|
+
- run: npm run build:plugins
|
|
47
|
+
- run: npm run test:plugins
|
|
48
|
+
- run: npm run pack:plugins
|
|
49
|
+
- name: Upload installable plugin tarballs
|
|
50
|
+
uses: actions/upload-artifact@v4
|
|
51
|
+
with:
|
|
52
|
+
name: native-plugin-packages
|
|
53
|
+
path: artifacts/plugins/*.tgz
|
|
54
|
+
if-no-files-found: error
|
|
28
55
|
|
|
29
56
|
pgvector-integration:
|
|
30
57
|
name: PostgreSQL pgvector integration
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
native-packages:
|
|
13
|
+
name: Build release plugin tarballs
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.11"
|
|
20
|
+
cache: pip
|
|
21
|
+
- name: Check Python, plugin and tag versions
|
|
22
|
+
env:
|
|
23
|
+
RELEASE_TAG: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }}
|
|
24
|
+
run: |
|
|
25
|
+
python - <<'PY'
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
import tomllib
|
|
30
|
+
|
|
31
|
+
version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
|
|
32
|
+
for agent in ("pi", "opencode", "omp"):
|
|
33
|
+
path = Path("plugins") / agent / "package.json"
|
|
34
|
+
manifest = json.loads(path.read_text())
|
|
35
|
+
if manifest["name"] != f"luminary-memory-{agent}" or manifest["version"] != version:
|
|
36
|
+
raise SystemExit(f"{path}: package name/version does not match Python {version}")
|
|
37
|
+
tag = os.environ["RELEASE_TAG"]
|
|
38
|
+
if tag and tag != f"v{version}":
|
|
39
|
+
raise SystemExit(f"Tag {tag!r} does not match Python/plugin version v{version}")
|
|
40
|
+
PY
|
|
41
|
+
- name: Install the actual Python bridge
|
|
42
|
+
run: python -m pip install -e ".[dev]"
|
|
43
|
+
- uses: actions/setup-node@v4
|
|
44
|
+
with:
|
|
45
|
+
node-version: "22"
|
|
46
|
+
check-latest: true
|
|
47
|
+
- run: npm ci --ignore-scripts
|
|
48
|
+
- run: npm run build:plugins
|
|
49
|
+
- run: npm run test:plugins
|
|
50
|
+
- run: npm run pack:plugins
|
|
51
|
+
- name: Check complete, version-matched release tarballs
|
|
52
|
+
run: |
|
|
53
|
+
python - <<'PY'
|
|
54
|
+
import json
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
import tarfile
|
|
57
|
+
import tomllib
|
|
58
|
+
|
|
59
|
+
version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
|
|
60
|
+
expected = {f"luminary-memory-{agent}-{version}.tgz" for agent in ("pi", "opencode", "omp")}
|
|
61
|
+
directory = Path("artifacts/plugins")
|
|
62
|
+
actual = {path.name for path in directory.glob("*.tgz")}
|
|
63
|
+
if actual != expected:
|
|
64
|
+
raise SystemExit(f"Expected tarballs {sorted(expected)}, got {sorted(actual)}")
|
|
65
|
+
for filename in sorted(expected):
|
|
66
|
+
with tarfile.open(directory / filename, "r:gz") as archive:
|
|
67
|
+
manifest = json.load(archive.extractfile("package/package.json"))
|
|
68
|
+
if filename != f'{manifest["name"]}-{manifest["version"]}.tgz' or manifest["version"] != version:
|
|
69
|
+
raise SystemExit(f"{filename}: packed manifest name/version mismatch")
|
|
70
|
+
for member in ("package/dist/index.js", "package/README.md", "package/LICENSE"):
|
|
71
|
+
entry = archive.getmember(member)
|
|
72
|
+
if not entry.isfile() or entry.size == 0:
|
|
73
|
+
raise SystemExit(f"{filename}: missing or empty {member}")
|
|
74
|
+
PY
|
|
75
|
+
- name: Upload validated plugin tarballs
|
|
76
|
+
uses: actions/upload-artifact@v4
|
|
77
|
+
with:
|
|
78
|
+
name: native-plugin-packages
|
|
79
|
+
path: artifacts/plugins/*.tgz
|
|
80
|
+
if-no-files-found: error
|
|
81
|
+
|
|
82
|
+
real-model:
|
|
83
|
+
# Release gate. Runs public strict recall against the real default
|
|
84
|
+
# embedding model on an isolated SQLite store and asserts which facts come
|
|
85
|
+
# back: the current scoped fact must be retrieved, an off-topic but
|
|
86
|
+
# graph-linked row must not be, cross-scope and expired rows stay out, and
|
|
87
|
+
# unanswerable queries abstain. This fails closed: if the model cannot be
|
|
88
|
+
# downloaded or run, the release does not happen.
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
- uses: actions/setup-python@v5
|
|
93
|
+
with:
|
|
94
|
+
python-version: "3.11"
|
|
95
|
+
cache: pip
|
|
96
|
+
- name: Install package with the real embedding engine
|
|
97
|
+
run: |
|
|
98
|
+
python -m pip install --upgrade pip
|
|
99
|
+
pip install -e ".[dev]"
|
|
100
|
+
- name: Gate on public strict recall with the default model
|
|
101
|
+
run: python scripts/smoke-real-model.py --report real-model-gate.json
|
|
102
|
+
- name: Upload gate report
|
|
103
|
+
if: always()
|
|
104
|
+
uses: actions/upload-artifact@v4
|
|
105
|
+
with:
|
|
106
|
+
name: real-model-gate
|
|
107
|
+
path: real-model-gate.json
|
|
108
|
+
if-no-files-found: ignore
|
|
109
|
+
|
|
110
|
+
pypi:
|
|
111
|
+
needs: [real-model, native-packages]
|
|
112
|
+
runs-on: ubuntu-latest
|
|
113
|
+
environment:
|
|
114
|
+
name: pypi
|
|
115
|
+
url: https://pypi.org/project/luminary-memory
|
|
116
|
+
permissions:
|
|
117
|
+
contents: write
|
|
118
|
+
id-token: write
|
|
119
|
+
steps:
|
|
120
|
+
- uses: actions/checkout@v4
|
|
121
|
+
- uses: actions/setup-python@v5
|
|
122
|
+
with:
|
|
123
|
+
python-version: "3.11"
|
|
124
|
+
cache: pip
|
|
125
|
+
- name: Build sdist and wheel
|
|
126
|
+
run: |
|
|
127
|
+
python -m pip install --upgrade pip
|
|
128
|
+
pip install build
|
|
129
|
+
python -m build
|
|
130
|
+
- name: Download validated plugin tarballs
|
|
131
|
+
uses: actions/download-artifact@v4
|
|
132
|
+
with:
|
|
133
|
+
name: native-plugin-packages
|
|
134
|
+
path: artifacts/plugins
|
|
135
|
+
- name: Build Hermes skill artifact
|
|
136
|
+
run: |
|
|
137
|
+
mkdir -p skill_asset
|
|
138
|
+
zip -j skill_asset/luminary-memory-skill.zip hermes/SKILL.md hermes/README.md
|
|
139
|
+
ls -lh skill_asset/luminary-memory-skill.zip
|
|
140
|
+
- name: Publish to PyPI (trusted publishing / OIDC)
|
|
141
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
142
|
+
# Trusted Publisher only — no API token. Configured at
|
|
143
|
+
# https://pypi.org/manage/account/publishing/. Never fall back to twine:
|
|
144
|
+
# an API token upload alongside Trusted Publishing triggers a PyPI alert.
|
|
145
|
+
- name: Attach skill and native plugin assets to GitHub Release
|
|
146
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
147
|
+
uses: softprops/action-gh-release@v2
|
|
148
|
+
with:
|
|
149
|
+
files: |
|
|
150
|
+
skill_asset/luminary-memory-skill.zip
|
|
151
|
+
artifacts/plugins/*.tgz
|
|
152
|
+
fail_on_unmatched_files: true
|
|
153
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
154
|
+
|
|
155
|
+
npm:
|
|
156
|
+
name: Publish configured npm plugins
|
|
157
|
+
needs: [pypi, native-packages]
|
|
158
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') && vars.PUBLISH_NPM_PLUGINS == 'true'
|
|
159
|
+
runs-on: ubuntu-latest
|
|
160
|
+
environment:
|
|
161
|
+
name: npm
|
|
162
|
+
permissions:
|
|
163
|
+
contents: read
|
|
164
|
+
id-token: write
|
|
165
|
+
steps:
|
|
166
|
+
- uses: actions/checkout@v4
|
|
167
|
+
- uses: actions/setup-node@v4
|
|
168
|
+
with:
|
|
169
|
+
node-version: "22"
|
|
170
|
+
check-latest: true
|
|
171
|
+
- name: Install an npm CLI with trusted publishing support
|
|
172
|
+
run: npm install --global 'npm@^11.5.1' --ignore-scripts
|
|
173
|
+
- name: Download the exact validated release tarballs
|
|
174
|
+
uses: actions/download-artifact@v4
|
|
175
|
+
with:
|
|
176
|
+
name: native-plugin-packages
|
|
177
|
+
path: artifacts/plugins
|
|
178
|
+
- name: Publish built tarballs using npm trusted publishing
|
|
179
|
+
env:
|
|
180
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
181
|
+
run: |
|
|
182
|
+
set -euo pipefail
|
|
183
|
+
version="${RELEASE_TAG#v}"
|
|
184
|
+
for agent in pi opencode omp; do
|
|
185
|
+
archive="artifacts/plugins/luminary-memory-${agent}-${version}.tgz"
|
|
186
|
+
test -s "$archive"
|
|
187
|
+
done
|
|
188
|
+
for agent in pi opencode omp; do
|
|
189
|
+
archive="artifacts/plugins/luminary-memory-${agent}-${version}.tgz"
|
|
190
|
+
npm publish "$archive" --access public --ignore-scripts --registry https://registry.npmjs.org
|
|
191
|
+
done
|
|
@@ -23,6 +23,11 @@ sdist/
|
|
|
23
23
|
var/
|
|
24
24
|
wheels/
|
|
25
25
|
|
|
26
|
+
# ---- Native plugin packages ----
|
|
27
|
+
node_modules/
|
|
28
|
+
artifacts/plugins/
|
|
29
|
+
plugins/*/LICENSE
|
|
30
|
+
|
|
26
31
|
# ---- Virtual environments ----
|
|
27
32
|
.venv/
|
|
28
33
|
venv/
|
|
@@ -97,6 +102,7 @@ REPORT-*.md
|
|
|
97
102
|
|
|
98
103
|
# ---- Local documentation and planning (keep out of source) ----
|
|
99
104
|
docs/*
|
|
105
|
+
!docs/agent-integrations.md
|
|
100
106
|
|
|
101
107
|
# ---- Generated API docs (regenerate via pdoc) ----
|
|
102
108
|
docs/api/
|
|
@@ -1,5 +1,114 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Harness-neutral UTF-8 JSON memory bridge with exact user/workspace/agent
|
|
8
|
+
ownership, strict recall, synchronous explicit writes, ID-scoped retraction,
|
|
9
|
+
current activity snapshots, and opt-in user-evidenced automatic curation.
|
|
10
|
+
- Packaged native OpenCode V2 2.1.4, pi and omp adapters, installed with
|
|
11
|
+
`luminary-memory hook install`. Native tools plus pi/omp `/luminary` commands
|
|
12
|
+
support terminal interaction and serializable results for compatible clients.
|
|
13
|
+
Existing config and unrelated dependencies are preserved.
|
|
14
|
+
- Supported-harness capability/setup guide, generic subprocess contract and
|
|
15
|
+
explicit desktop/web/Telegram interaction limits.
|
|
16
|
+
- Luminary-maintained native npm package sources for pi, OpenCode and omp, built
|
|
17
|
+
from the canonical adapters with a locked Node/esbuild workspace. Installable
|
|
18
|
+
tarballs contain compiled ESM and native discovery metadata without bundling
|
|
19
|
+
host frameworks or embedding a maintainer's Python path.
|
|
20
|
+
- Plugin build/consumer checks, version-synchronized release artifacts and
|
|
21
|
+
explicitly opt-in npm trusted publishing after the Python release gates.
|
|
22
|
+
- Published initial `0.3.1` npm packages for pi, OpenCode and omp with verified
|
|
23
|
+
registry checksums and native installation/loading. Python bridge setup uses
|
|
24
|
+
a pinned public source commit until the next coordinated Python release.
|
|
25
|
+
- Submitted OpenCode Ecosystem PR #58823 and pi's release-gated `pi-package`
|
|
26
|
+
discovery metadata. Catalog indexing and upstream approval remain separate
|
|
27
|
+
from successful npm publication.
|
|
28
|
+
- Migrated the OpenCode `0.3.2` adapter to the actual V2 CLI/SDK namespace,
|
|
29
|
+
`@opencode/cli` and `@opencode/plugin` 2.1.4: default `Plugin.define`,
|
|
30
|
+
Promise domain APIs, plural `plugins`, native tools/progress/context hooks,
|
|
31
|
+
and successful-execution retention with per-session workspace ownership.
|
|
32
|
+
Real V2 sessions and SQLite verified memory operations, cross-workspace
|
|
33
|
+
isolation, automatic recall, user-grounded curation, rejection of
|
|
34
|
+
assistant-only claims, and removal cleanup. The old V1-only listing patch
|
|
35
|
+
was removed; the legacy Ecosystem PR is not a verified V2 listing.
|
|
36
|
+
|
|
37
|
+
## [0.3.1] - 2026-10-25
|
|
38
|
+
|
|
39
|
+
Measurement and recall-calibration release. No public API breaks; the default
|
|
40
|
+
embedding model answers more paraphrases without loosening the abstention guard,
|
|
41
|
+
and releases are now gated on real-model recall instead of a green unit suite
|
|
42
|
+
alone.
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- **Release gate on public strict recall** — `.github/workflows/publish.yml` had
|
|
47
|
+
no real-model job, so a release could ship while strict recall returned a
|
|
48
|
+
confident wrong answer. `scripts/smoke-real-model.py` drives
|
|
49
|
+
`MemoryClient.recall` end to end with the real default model on an isolated
|
|
50
|
+
store and asserts which facts come back, including abstention, scope isolation
|
|
51
|
+
and expiry. `pypi` requires it and fails closed.
|
|
52
|
+
- **`--engine real|fake` for gold evaluation** — accuracy runs can use the real
|
|
53
|
+
embedding model while the latency smoke keeps its deterministic engine.
|
|
54
|
+
Reports record engine, model, Python/NumPy/Fastembed versions, the evaluation
|
|
55
|
+
clock, and per-case returned/excluded ids.
|
|
56
|
+
- **Recorded baseline** — `benchmarks/baselines/gold-real-v1.json`.
|
|
57
|
+
- **Extended gold fixture** — `benchmarks/gold_extended.jsonl` (28 memories, 15
|
|
58
|
+
cases) plus `build_gold_extended.py`. Kept out of CI while it is red; it is the
|
|
59
|
+
instrument for the remaining retrieval defects.
|
|
60
|
+
- **Long-run soak harness** — `scripts/soak-test.py` drives ingest, recall and
|
|
61
|
+
lifecycle through hundreds of cycles on one store and fails on a lost control
|
|
62
|
+
fact, a no-answer query that starts answering, or recall p50 growing more than
|
|
63
|
+
3x across the run. A bounded version runs in the normal suite.
|
|
64
|
+
- **Validity-window regression tests** — past-`valid_to` and future-`valid_from`
|
|
65
|
+
rows were already excluded in both strict and permissive mode, but nothing
|
|
66
|
+
pinned it. Four tests now do, verified to fail when the comparison is removed.
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- **Semantic-evidence floor is model-scoped and re-measured** — a single global
|
|
71
|
+
`0.78` cosine constant threw away correct paraphrases whose lexical coverage
|
|
72
|
+
was also low. `config.semantic_support_floor()` now returns a floor measured
|
|
73
|
+
per embedding model, `0.74` for `BAAI/bge-small-en-v1.5`, and keeps the
|
|
74
|
+
conservative `0.78` for any unmeasured model so an unmeasured model can only
|
|
75
|
+
abstain more.
|
|
76
|
+
|
|
77
|
+
The value comes from a sweep over two fixtures plus the release gate. It is
|
|
78
|
+
deliberately the lowest floor that stops a grounded but off-topic row from
|
|
79
|
+
being returned: that row's cosine is `0.7098`, which a `0.70` floor admitted.
|
|
80
|
+
On the controlled micro fixture the result is recall@10 `0.70` with
|
|
81
|
+
**`wrong_hit_rate` 0.00** and abstention 1.00; the extended fixture improves
|
|
82
|
+
from 0.25 to 0.08 wrong-hit. Some recall is given up on purpose — for a memory
|
|
83
|
+
layer a wrong answer is worse than an abstention.
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- **Gold evaluation is date-invariant** — fixture timestamps are rebased so the
|
|
88
|
+
newest `observed_at` equals run time, preserving relative ages and validity
|
|
89
|
+
windows. The same commit now scores the same on any date.
|
|
90
|
+
- **Grounding is no longer reported as relevance** — `evidence_support_precision`
|
|
91
|
+
counted a fully sourced but off-topic row as supported. It is replaced by
|
|
92
|
+
`wrong_hit_rate` / `wrong_hit_rows` / per-case `wrong_hit_ids` for relevance
|
|
93
|
+
and `source_grounded_rate` for stored-source grounding.
|
|
94
|
+
|
|
95
|
+
### Documented
|
|
96
|
+
|
|
97
|
+
- **Consolidation converges, it is not idempotent** — clustering is greedy and
|
|
98
|
+
single-pass, so a row similar to several others can be claimed by one cluster
|
|
99
|
+
and never compared against the rest. On a 25-memory store the observed shape is
|
|
100
|
+
`25 → 14 → 13 → 13`; schedule more than one pass after a bulk import.
|
|
101
|
+
- **Unbounded ledger growth** — `episodes`, `memory_events` and
|
|
102
|
+
`memory_evidence` are append-only and untouched by `run_lifecycle()`. A direct
|
|
103
|
+
`ingest()` stores a verbatim episode copy of content already in `memories`, so
|
|
104
|
+
a long-lived store holds two copies of every fact with no retention bound.
|
|
105
|
+
- **Query expansion can worsen ranking** — keeping the original query tokens does
|
|
106
|
+
not bound the result. Measured on the default model: the correct deploy fact
|
|
107
|
+
ranks `0.6495` against an unrelated docs URL at `0.6255`, but after expansion
|
|
108
|
+
the docs URL rises to `0.8084` and the deploy fact to `0.7074`. Documented as
|
|
109
|
+
an open defect with the measured values.
|
|
110
|
+
|
|
111
|
+
|
|
3
112
|
## [0.3.0] - 2026-08-24
|
|
4
113
|
|
|
5
114
|
### Summary
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping build luminary-memory.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone <repo> && cd luminary-memory
|
|
9
|
+
pip install -e ".[dev]"
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Development workflow
|
|
13
|
+
|
|
14
|
+
1. Create a branch from `develop`: `git checkout develop && git checkout -b feat/your-change`.
|
|
15
|
+
2. Write a failing test first (`tests/`).
|
|
16
|
+
3. Implement the minimal change.
|
|
17
|
+
4. Update the tracked guide that owns the changed contract and the matching
|
|
18
|
+
static website guide in `website/js/docs-guides.js`. Keep ignored planning
|
|
19
|
+
notes under `docs/` out of the public source.
|
|
20
|
+
5. Run the checks:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python -m pytest
|
|
24
|
+
python -m ruff check src tests hermes/hooks
|
|
25
|
+
node --check website/js/docs-guides.js
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
5. Commit with a conventional message.
|
|
29
|
+
|
|
30
|
+
### Native plugin packages
|
|
31
|
+
|
|
32
|
+
Use the latest Node.js 22 patch (at least 22.22.2) and Python 3.11+ from the
|
|
33
|
+
repository root:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python -m pip install -e ".[dev]"
|
|
37
|
+
npm ci --ignore-scripts
|
|
38
|
+
npm run build:plugins
|
|
39
|
+
npm run test:plugins
|
|
40
|
+
npm run pack:plugins
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The private root npm workspace is build tooling, not a publishable package.
|
|
44
|
+
The three Luminary-maintained packages are `luminary-memory-pi`,
|
|
45
|
+
`luminary-memory-opencode`, and `luminary-memory-omp`. "Maintained" does not
|
|
46
|
+
imply endorsement by pi, OpenCode or omp, ownership of an npm name, or that an
|
|
47
|
+
npm release already exists.
|
|
48
|
+
|
|
49
|
+
Edit the canonical adapters under
|
|
50
|
+
`src/luminary_memory/integrations/assets/`, not generated bundles. The build
|
|
51
|
+
produces each `plugins/<agent>/dist/index.js` and copies the root license into
|
|
52
|
+
the package. **A source checkout of `plugins/<agent>` without a build has no
|
|
53
|
+
`dist` entry point and is not an installable plugin.** Packaging writes local
|
|
54
|
+
installable tarballs to `artifacts/plugins/*.tgz`; it does not publish them.
|
|
55
|
+
Use the instructions in each package README to install a built local directory
|
|
56
|
+
or tarball into its host.
|
|
57
|
+
|
|
58
|
+
The Node tests must be able to start the real Python bridge. Keep the editable
|
|
59
|
+
Python installation available on `PATH`, or set `LUMINARY_PYTHON` to its Python
|
|
60
|
+
executable. Package installation never installs Python dependencies, downloads
|
|
61
|
+
models or runs an automatic pip/postinstall script. The existing Python-wheel
|
|
62
|
+
copy installer is a separate installation path; remove copied hooks before
|
|
63
|
+
enabling a native package so memory events are not registered twice.
|
|
64
|
+
|
|
65
|
+
CI runs these same npm commands on the latest Node 22 patch with Python 3.11
|
|
66
|
+
and an editable Python installation, then uploads the tarballs as the
|
|
67
|
+
`native-plugin-packages` artifact. The real-model release gate below remains
|
|
68
|
+
separate from the package tests.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## Branch model
|
|
72
|
+
|
|
73
|
+
- **`develop`**, integration branch. **All pull requests target `develop`.**
|
|
74
|
+
- **`main`**, stable release branch, protected. Only maintainers merge release
|
|
75
|
+
commits into it (feature → develop → main → tag).
|
|
76
|
+
|
|
77
|
+
## Release gate
|
|
78
|
+
|
|
79
|
+
Tagging `v*` publishes to PyPI through `.github/workflows/publish.yml`, and
|
|
80
|
+
`pypi` has a hard prerequisite: the `real-model` job. It runs
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
python scripts/smoke-real-model.py --report real-model-gate.json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
which drives public `MemoryClient.recall` end to end on an isolated SQLite store
|
|
87
|
+
with the real default embedding model and asserts **which facts come back**:
|
|
88
|
+
|
|
89
|
+
- the current scoped deploy fact for both an exact and a paraphrased question;
|
|
90
|
+
- an off-topic but graph-linked documentation row is not returned;
|
|
91
|
+
- an expired row, another tenant's row and a scoped query stay inside their
|
|
92
|
+
boundaries;
|
|
93
|
+
- unanswerable queries abstain.
|
|
94
|
+
|
|
95
|
+
It fails closed — a wrong model, a failed download or a failed inference aborts
|
|
96
|
+
the job — and the JSON report is uploaded as an artifact even when it fails.
|
|
97
|
+
Run it locally before tagging; it is not part of the unit suite because it needs
|
|
98
|
+
the real ONNX model.
|
|
99
|
+
|
|
100
|
+
A gate that passes on a confident wrong answer is worse than no gate. When the
|
|
101
|
+
gate fails, fix the retrieval defect; never relax the gate or swap in a stub
|
|
102
|
+
embedder.
|
|
103
|
+
|
|
104
|
+
### Versioning and release assets
|
|
105
|
+
|
|
106
|
+
Before a release, use the existing version synchronizer from the repository
|
|
107
|
+
root, for example:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
bash scripts/bump-version.sh 0.3.2
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
It synchronizes the Python version, all three plugin manifest versions and the
|
|
114
|
+
workspace versions in `package-lock.json`, preserving other JSON metadata.
|
|
115
|
+
The private root `package.json` has no version. Review the generated changelog
|
|
116
|
+
entry, then run the Python checks, native package commands and real-model gate
|
|
117
|
+
before committing the release changes and creating the matching `vX.Y.Z` tag.
|
|
118
|
+
|
|
119
|
+
The publish workflow builds, tests and packs native plugins, checks that every
|
|
120
|
+
manifest matches `pyproject.toml`, and verifies the exact three nonempty
|
|
121
|
+
tarballs contain a built entry point, README and license. Tag releases must
|
|
122
|
+
also match `v<version>`. Both this package job and the existing real-model gate
|
|
123
|
+
must pass before PyPI publication. After PyPI succeeds, tag pushes attach the
|
|
124
|
+
Hermes skill zip and those exact `.tgz` files to the GitHub release, even when
|
|
125
|
+
npm publication is disabled. Missing or mismatched packages fail closed.
|
|
126
|
+
|
|
127
|
+
Manual `workflow_dispatch` keeps the Python publication path: it performs the
|
|
128
|
+
same gates and builds, but does not create GitHub release assets or publish to
|
|
129
|
+
npm, even if dispatched from a tag. A tag push, not a manual dispatch, is
|
|
130
|
+
required for those external release actions.
|
|
131
|
+
|
|
132
|
+
### Optional npm trusted publishing
|
|
133
|
+
|
|
134
|
+
npm publication is **disabled unless** the repository Actions variable
|
|
135
|
+
`PUBLISH_NPM_PLUGINS` is exactly `true`. Leave it unset while establishing
|
|
136
|
+
package ownership and registry configuration. Local builds and downloadable
|
|
137
|
+
release tarballs do not require npm publishing access.
|
|
138
|
+
|
|
139
|
+
Before enabling it:
|
|
140
|
+
|
|
141
|
+
1. Establish maintainer-controlled ownership of all three exact npm names:
|
|
142
|
+
`luminary-memory-pi`, `luminary-memory-opencode`, and `luminary-memory-omp`.
|
|
143
|
+
Availability is not ownership. Complete any initial package creation or
|
|
144
|
+
authenticated bootstrap required by npm separately; this workflow does not
|
|
145
|
+
reserve names or pretend to bootstrap trusted publishing.
|
|
146
|
+
2. Configure an npm **trusted publisher for each package** for the correct
|
|
147
|
+
GitHub owner/repository, workflow filename `publish.yml`, and environment
|
|
148
|
+
name `npm`. Allow direct `npm publish` (a stage-only publisher cannot run
|
|
149
|
+
this workflow). Each manifest's `repository.url` must match that GitHub
|
|
150
|
+
repository. See [npm's trusted publishing requirements](https://docs.npmjs.com/trusted-publishers/).
|
|
151
|
+
3. Configure the GitHub `npm` deployment environment and its protection rules;
|
|
152
|
+
keep the existing `pypi` environment and PyPI trusted publisher configured
|
|
153
|
+
independently. Protect release tags and restrict who can change the opt-in
|
|
154
|
+
variable or approve deployments.
|
|
155
|
+
4. Only after all three package publishers are ready, set the repository
|
|
156
|
+
variable `PUBLISH_NPM_PLUGINS=true` and push a new, version-matched tag.
|
|
157
|
+
|
|
158
|
+
The npm job runs on a GitHub-hosted runner with the latest Node 22 patch and
|
|
159
|
+
npm `^11.5.1` (trusted publishing requires npm 11.5.1+ and Node 22.14+).
|
|
160
|
+
It requests `id-token: write`, downloads the already validated tarballs from
|
|
161
|
+
the same workflow run, and publishes each exact tarball only after the
|
|
162
|
+
real-model gate and PyPI job succeed. It never rebuilds a package at publish
|
|
163
|
+
time. Publishing uses `--access public --ignore-scripts` against
|
|
164
|
+
`https://registry.npmjs.org`; no npm token secret, credential logging or
|
|
165
|
+
token-based fallback is configured.
|
|
166
|
+
|
|
167
|
+
The workflow's default permission is `contents: read`. The PyPI job requests
|
|
168
|
+
`id-token: write` for its existing trusted publishing and `contents: write` to
|
|
169
|
+
attach GitHub release assets; the optional npm job requests only
|
|
170
|
+
`contents: read` and `id-token: write`. Neither local development commands nor
|
|
171
|
+
manual Python releases force npm publication.
|
|
172
|
+
|
|
173
|
+
The three npm uploads are sequential, not transactional. If registry
|
|
174
|
+
authorization or an upload fails, the job fails; it does not mask the error,
|
|
175
|
+
republish an existing immutable version or fall back to credentials. Inspect
|
|
176
|
+
which versions actually reached npm before planning recovery. Fix npm
|
|
177
|
+
configuration without rerunning a successful PyPI upload blindly; npm
|
|
178
|
+
publication must continue to use the validated release tarballs.
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
## Commit conventions
|
|
182
|
+
|
|
183
|
+
- `feat:`, new feature
|
|
184
|
+
- `fix:`, bug fix
|
|
185
|
+
- `docs:`, documentation only
|
|
186
|
+
- `improve:`, refactor or enhancement without behavior change
|
|
187
|
+
- `chore:`, build/tooling
|
|
188
|
+
|
|
189
|
+
## Coding standards
|
|
190
|
+
|
|
191
|
+
- Python 3.11+, type-hinted.
|
|
192
|
+
- `ruff` clean, `pytest` green.
|
|
193
|
+
- TDD where feasible, test first, then implement.
|
|
194
|
+
- Keep the public API (`MemoryClient`) stable; add rather than break.
|
|
195
|
+
- Full-source coverage is reported and must not regress from the current
|
|
196
|
+
evidence-backed baseline (`83%`, 5,037 statements). Every changed behavior
|
|
197
|
+
needs a targeted regression or invariant test; do not inflate coverage with
|
|
198
|
+
tests that only execute lines without checking outcomes. PostgreSQL-only
|
|
199
|
+
branches are verified separately by the pgvector integration job.
|
|
200
|
+
|
|
201
|
+
### Long-run checks
|
|
202
|
+
|
|
203
|
+
Changes to ingest, recall, lifecycle or retention must also survive a soak run,
|
|
204
|
+
because those defects only appear across cycles:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
python scripts/soak-test.py --cycles 400 --per-cycle 5 --report /tmp/soak.json
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
It fails on a lost control fact, a no-answer query that starts returning rows,
|
|
211
|
+
or recall p50 growing more than `3x` between the first and last fifth of the
|
|
212
|
+
run. See [Lifecycle](docs/lifecycle.md#long-run-behaviour) for what it measures
|
|
213
|
+
and the current observed numbers.
|
|
214
|
+
|
|
215
|
+
## AI assistance notice
|
|
216
|
+
|
|
217
|
+
If you use **any kind of AI assistance** to contribute to luminary-memory, please
|
|
218
|
+
disclose it in the pull request together with the extent of the usage. For
|
|
219
|
+
example:
|
|
220
|
+
|
|
221
|
+
> This PR was written primarily by Claude Code.
|
|
222
|
+
>
|
|
223
|
+
> I consulted ChatGPT to understand the codebase, but the solution was fully
|
|
224
|
+
> authored manually.
|
|
225
|
+
|
|
226
|
+
This helps reviewers apply the right level of scrutiny. AI assistance isn't
|
|
227
|
+
always perfect, even when used with the utmost care, a quick disclosure goes a
|
|
228
|
+
long way. Please don't use AI to write the pull request description or
|
|
229
|
+
contributor communication; keep it concise and in your own voice.
|
|
230
|
+
|
|
231
|
+
## Pull requests
|
|
232
|
+
|
|
233
|
+
- One logical change per PR.
|
|
234
|
+
- Target the **`develop`** branch.
|
|
235
|
+
- Link the issue if applicable.
|
|
236
|
+
- CI must pass before merge.
|
|
237
|
+
- Automated checks run on every PR:
|
|
238
|
+
- **CI**, unit tests (Python 3.11 & 3.12) + lint.
|
|
239
|
+
- **pgvector integration**, real Postgres round-trips (HNSW, JSONB, rollback).
|
|
240
|
+
- **Native plugin packages**, Node 22 build/tests/local pack with the actual
|
|
241
|
+
Python bridge available; uploads all three installable `.tgz` artifacts.
|
|
242
|
+
- **Triage**, auto-labels the PR and welcomes first-time contributors.
|
|
243
|
+
- **Contributor check**, a soft account/language triage hint for maintainers.
|
|
244
|
+
|
|
245
|
+
## Testing
|
|
246
|
+
|
|
247
|
+
Run the full suite (SQLite + unit tests) locally:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
python -m pytest # 505 passed, 3 skipped at the current baseline
|
|
251
|
+
python -m ruff check src tests hermes/hooks
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Coverage (full-source baseline):
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
python -m pytest --cov=luminary_memory --cov-report=term
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The current local baseline is `83%` (`5,037` statements, `881` missed). The
|
|
261
|
+
number is intentionally reported honestly while the defensive PostgreSQL and
|
|
262
|
+
failure branches continue to receive integration coverage; the quality gate
|
|
263
|
+
is the invariant-focused test suite plus the CI/verification coverage gate
|
|
264
|
+
`--fail-under=82`.
|
|
265
|
+
|
|
266
|
+
### Postgres / pgvector integration tests
|
|
267
|
+
|
|
268
|
+
`tests/test_backend_pgvector.py` contains real-Postgres round-trips that are
|
|
269
|
+
**skipped unless `LUMINARY_PG_DSN` is set**. CI provides a Postgres service for
|
|
270
|
+
these (see `.github/workflows/ci.yml`). To run them locally:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
# spin up a throwaway Postgres with the pgvector extension
|
|
274
|
+
docker run -d --name luminary-pg -p 5432:5432 \
|
|
275
|
+
-e POSTGRES_USER=luminary -e POSTGRES_PASSWORD=luminary -e POSTGRES_DB=luminary \
|
|
276
|
+
pgvector/pgvector:pg16
|
|
277
|
+
|
|
278
|
+
# point the tests at it
|
|
279
|
+
export LUMINARY_PG_DSN=postgresql://luminary:***@localhost:5432/luminary
|
|
280
|
+
python -m pytest tests/test_backend_pgvector.py -v
|
|
281
|
+
```
|