zettelforge 2.2.0__tar.gz → 2.3.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.
Files changed (227) hide show
  1. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/workflows/ci.yml +2 -1
  2. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/workflows/docs.yml +2 -2
  3. {zettelforge-2.2.0 → zettelforge-2.3.0}/.gitignore +4 -1
  4. zettelforge-2.3.0/ARCHITECTURE.md +42 -0
  5. {zettelforge-2.2.0 → zettelforge-2.3.0}/CHANGELOG.md +143 -0
  6. {zettelforge-2.2.0 → zettelforge-2.3.0}/PKG-INFO +37 -33
  7. {zettelforge-2.2.0 → zettelforge-2.3.0}/README.md +29 -29
  8. {zettelforge-2.2.0 → zettelforge-2.3.0}/SECURITY.md +17 -11
  9. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/BENCHMARK_REPORT.md +45 -19
  10. {zettelforge-2.2.0 → zettelforge-2.3.0}/config.default.yaml +49 -17
  11. zettelforge-2.3.0/docs/architecture-diagram.mmd +202 -0
  12. zettelforge-2.3.0/docs/archive/README.md +11 -0
  13. zettelforge-2.3.0/docs/assets/ZettelForge_Architecture.mmd +185 -0
  14. zettelforge-2.3.0/docs/assets/architecture-overview.mmd +57 -0
  15. zettelforge-2.3.0/docs/assets/architecture-read-path.mmd +140 -0
  16. zettelforge-2.3.0/docs/assets/architecture-write-path.mmd +122 -0
  17. zettelforge-2.3.0/docs/assets/zettelforge_architecture.svg +77 -0
  18. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/explanation/architecture.md +1 -1
  19. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/explanation/stix-in-zettelforge.md +1 -1
  20. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/integrate-llm-agent.md +1 -1
  21. zettelforge-2.3.0/docs/how-to/migrate-jsonl-to-sqlite.md +112 -0
  22. zettelforge-2.3.0/docs/how-to/reproduce-benchmarks.md +120 -0
  23. zettelforge-2.3.0/docs/how-to/troubleshoot.md +180 -0
  24. zettelforge-2.3.0/docs/how-to/upgrade.md +94 -0
  25. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/index.md +4 -4
  26. zettelforge-2.3.0/docs/llms.txt +64 -0
  27. zettelforge-2.3.0/docs/narrative/2026-04-16-the-memory-problem.md +86 -0
  28. zettelforge-2.3.0/docs/overrides/main.html +82 -0
  29. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/reference/configuration.md +39 -10
  30. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/reference/governance-controls.md +2 -2
  31. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/reference/memory-manager-api.md +1 -1
  32. zettelforge-2.3.0/docs/rfcs/RFC-001-conversational-entity-extractor.md +356 -0
  33. zettelforge-2.3.0/docs/rfcs/RFC-002-universal-llm-provider.md +883 -0
  34. zettelforge-2.3.0/docs/rfcs/RFC-003-adversarial-review.md +393 -0
  35. zettelforge-2.3.0/docs/rfcs/RFC-003-read-path-depth-routing.md +936 -0
  36. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-15-causal-graph.md +36 -0
  37. zettelforge-2.3.0/docs/superpowers/research/2026-04-15-format-stability.md +1029 -0
  38. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-15-memory-evolution.md +41 -1
  39. zettelforge-2.3.0/docs/superpowers/research/2026-04-15-merge-consolidation.md +372 -0
  40. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-15-persistence-semantics.md +50 -0
  41. zettelforge-2.3.0/docs/superpowers/research/README.md +40 -0
  42. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/superpowers/specs/2026-04-15-p1-features-prd.md +197 -29
  43. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/tutorials/01-quickstart.md +3 -3
  44. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/tutorials/02-first-cti-report.md +2 -2
  45. {zettelforge-2.2.0 → zettelforge-2.3.0}/mkdocs.yml +23 -2
  46. {zettelforge-2.2.0 → zettelforge-2.3.0}/pyproject.toml +12 -4
  47. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/__init__.py +14 -10
  48. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/backend_factory.py +21 -0
  49. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/cache.py +7 -3
  50. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/config.py +117 -6
  51. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/entity_indexer.py +11 -3
  52. zettelforge-2.3.0/src/zettelforge/llm_client.py +287 -0
  53. zettelforge-2.3.0/src/zettelforge/llm_providers/__init__.py +84 -0
  54. zettelforge-2.3.0/src/zettelforge/llm_providers/base.py +59 -0
  55. zettelforge-2.3.0/src/zettelforge/llm_providers/local_provider.py +96 -0
  56. zettelforge-2.3.0/src/zettelforge/llm_providers/mock_provider.py +50 -0
  57. zettelforge-2.3.0/src/zettelforge/llm_providers/ollama_provider.py +56 -0
  58. zettelforge-2.3.0/src/zettelforge/llm_providers/registry.py +76 -0
  59. zettelforge-2.3.0/src/zettelforge/mcp/__init__.py +34 -0
  60. zettelforge-2.3.0/src/zettelforge/mcp/__main__.py +11 -0
  61. zettelforge-2.2.0/web/mcp_server.py → zettelforge-2.3.0/src/zettelforge/mcp/server.py +30 -40
  62. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/memory_manager.py +107 -3
  63. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/observability.py +8 -3
  64. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/ocsf.py +15 -1
  65. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/sqlite_backend.py +1 -1
  66. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/vector_retriever.py +12 -2
  67. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_core.py +4 -3
  68. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_langchain_retriever.py +13 -6
  69. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_llm_client.py +40 -20
  70. zettelforge-2.3.0/tests/test_llm_providers.py +318 -0
  71. zettelforge-2.3.0/tests/test_mcp_server.py +139 -0
  72. zettelforge-2.3.0/web/mcp_server.py +18 -0
  73. zettelforge-2.2.0/ARCHITECTURE.md +0 -36
  74. zettelforge-2.2.0/docs/llms.txt +0 -50
  75. zettelforge-2.2.0/docs/rfcs/RFC-001-conversational-entity-extractor.md +0 -113
  76. zettelforge-2.2.0/src/zettelforge/llm_client.py +0 -150
  77. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/CODEOWNERS +0 -0
  78. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  79. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  80. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/SECURITY.md +0 -0
  81. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/dependabot.yml +0 -0
  82. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/pull_request_template.md +0 -0
  83. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/workflows/publish.yml +0 -0
  84. {zettelforge-2.2.0 → zettelforge-2.3.0}/.github/workflows/snyk-security.yml +0 -0
  85. {zettelforge-2.2.0 → zettelforge-2.3.0}/CODEOWNERS +0 -0
  86. {zettelforge-2.2.0 → zettelforge-2.3.0}/CODE_OF_CONDUCT.md +0 -0
  87. {zettelforge-2.2.0 → zettelforge-2.3.0}/CONTRIBUTING.md +0 -0
  88. {zettelforge-2.2.0 → zettelforge-2.3.0}/Dockerfile +0 -0
  89. {zettelforge-2.2.0 → zettelforge-2.3.0}/GOVERNANCE.md +0 -0
  90. {zettelforge-2.2.0 → zettelforge-2.3.0}/LICENSE +0 -0
  91. {zettelforge-2.2.0 → zettelforge-2.3.0}/MANIFEST.in +0 -0
  92. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/LOCOMO_BENCHMARK_COMPARISON.md +0 -0
  93. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/auto_ralph.py +0 -0
  94. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/benchmark_harness.py +0 -0
  95. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/cti_benchmark_v2.py +0 -0
  96. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/cti_retrieval_benchmark.py +0 -0
  97. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/cti_retrieval_results.json +0 -0
  98. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/cti_v2_results.json +0 -0
  99. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/ctibench_benchmark.py +0 -0
  100. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/ctibench_results.json +0 -0
  101. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/dataset.json +0 -0
  102. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/enterprise-attack.json +0 -0
  103. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/evolve_benchmark.py +0 -0
  104. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/evolve_results.json +0 -0
  105. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/graph_test.py +0 -0
  106. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/locomo_benchmark.py +0 -0
  107. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/locomo_results.json +0 -0
  108. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/locomo_results_v1.3.0_baseline.json +0 -0
  109. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/memoryagentbench.py +0 -0
  110. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/memoryagentbench_results.json +0 -0
  111. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/mempalace_benchmark.py +0 -0
  112. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/mempalace_results.json +0 -0
  113. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/naive_memory.py +0 -0
  114. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/opencti_benchmark.py +0 -0
  115. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/ragas_benchmark.py +0 -0
  116. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/ragas_cti_results.json +0 -0
  117. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/ragas_results.json +0 -0
  118. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/results/benchmark_report.md +0 -0
  119. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/results/ralph_optimization_log.json +0 -0
  120. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/scale_benchmark.py +0 -0
  121. {zettelforge-2.2.0 → zettelforge-2.3.0}/benchmarks/scale_results.json +0 -0
  122. {zettelforge-2.2.0 → zettelforge-2.3.0}/config.example.yaml +0 -0
  123. {zettelforge-2.2.0 → zettelforge-2.3.0}/docker/docker-compose.yml +0 -0
  124. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/CNAME +0 -0
  125. {zettelforge-2.2.0 → zettelforge-2.3.0/docs/archive}/PACKAGE_SUMMARY.md +0 -0
  126. {zettelforge-2.2.0 → zettelforge-2.3.0/docs/archive}/SKILL.md +0 -0
  127. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/demo.gif +0 -0
  128. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/favicon.svg +0 -0
  129. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/logo.svg +0 -0
  130. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/social-preview.png +0 -0
  131. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/threatrecall-logo-philosophy.md +0 -0
  132. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/threatrecall-logo.png +0 -0
  133. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/threatrecall-logo.svg +0 -0
  134. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/threatrecall-mark.png +0 -0
  135. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/assets/threatrecall-mark.svg +0 -0
  136. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/explanation/epistemic-tiers.md +0 -0
  137. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/explanation/two-phase-pipeline.md +0 -0
  138. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/explanation/zettelkasten-philosophy.md +0 -0
  139. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/configure-lancedb.md +0 -0
  140. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/configure-opencti.md +0 -0
  141. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/configure-typedb.md +0 -0
  142. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/ingest-news-report.md +0 -0
  143. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/query-apt-tools.md +0 -0
  144. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/resolve-aliases.md +0 -0
  145. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/run-temporal-query.md +0 -0
  146. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/how-to/store-threat-actor.md +0 -0
  147. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/reference/retrieval-policies.md +0 -0
  148. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/reference/stix-schema.md +0 -0
  149. {zettelforge-2.2.0 → zettelforge-2.3.0}/docs/stylesheets/extra.css +0 -0
  150. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-09-ctibench-ragas-benchmarks.md +0 -0
  151. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-09-fastembed-local-embeddings.md +0 -0
  152. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-09-hybrid-typedb-lancedb-architecture.md +0 -0
  153. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-09-local-llm-llama-cpp.md +0 -0
  154. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-15-anti-aversion-cleanup.md +0 -0
  155. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-15-ctibench-ate-fix.md +0 -0
  156. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.3.0/docs/superpowers/research}/2026-04-15-sqlite-migration.md +0 -0
  157. {zettelforge-2.2.0 → zettelforge-2.3.0}/examples/athf_bridge.py +0 -0
  158. {zettelforge-2.2.0 → zettelforge-2.3.0}/examples/mcp_claude_code.md +0 -0
  159. {zettelforge-2.2.0 → zettelforge-2.3.0}/examples/quickstart.py +0 -0
  160. {zettelforge-2.2.0 → zettelforge-2.3.0}/governance/controls.yaml +0 -0
  161. {zettelforge-2.2.0 → zettelforge-2.3.0}/scripts/migrate_jsonl_to_sqlite.py +0 -0
  162. {zettelforge-2.2.0 → zettelforge-2.3.0}/scripts/rebuild_index.py +0 -0
  163. {zettelforge-2.2.0 → zettelforge-2.3.0}/scripts/record-demo.sh +0 -0
  164. {zettelforge-2.2.0 → zettelforge-2.3.0}/scripts/typedb-setup.sh +0 -0
  165. {zettelforge-2.2.0 → zettelforge-2.3.0}/scripts/zettelforge-rebuild.service +0 -0
  166. {zettelforge-2.2.0 → zettelforge-2.3.0}/scripts/zettelforge-rebuild.timer +0 -0
  167. {zettelforge-2.2.0 → zettelforge-2.3.0}/skills/claude-code-skill.md +0 -0
  168. {zettelforge-2.2.0 → zettelforge-2.3.0}/skills/openclaw-skill.md +0 -0
  169. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/__main__.py +0 -0
  170. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/alias_resolver.py +0 -0
  171. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/blended_retriever.py +0 -0
  172. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/consolidation.py +0 -0
  173. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/demo.py +0 -0
  174. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/edition.py +0 -0
  175. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/extensions.py +0 -0
  176. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/fact_extractor.py +0 -0
  177. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/governance_validator.py +0 -0
  178. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/graph_retriever.py +0 -0
  179. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/integrations/__init__.py +0 -0
  180. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/integrations/langchain_retriever.py +0 -0
  181. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/intent_classifier.py +0 -0
  182. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/json_parse.py +0 -0
  183. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/knowledge_graph.py +0 -0
  184. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/log.py +0 -0
  185. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/memory_evolver.py +0 -0
  186. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/memory_store.py +0 -0
  187. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/memory_updater.py +0 -0
  188. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/note_constructor.py +0 -0
  189. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/note_schema.py +0 -0
  190. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/ontology.py +0 -0
  191. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/retry.py +0 -0
  192. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/storage_backend.py +0 -0
  193. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/synthesis_generator.py +0 -0
  194. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/synthesis_validator.py +0 -0
  195. {zettelforge-2.2.0 → zettelforge-2.3.0}/src/zettelforge/vector_memory.py +0 -0
  196. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/__init__.py +0 -0
  197. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/benchmark_scale.py +0 -0
  198. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/conftest.py +0 -0
  199. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_basic.py +0 -0
  200. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_blended_retriever.py +0 -0
  201. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_causal_extraction.py +0 -0
  202. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_config.py +0 -0
  203. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_consolidation.py +0 -0
  204. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_conversational_entities.py +0 -0
  205. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_cti_integration.py +0 -0
  206. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_edition.py +0 -0
  207. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_embedding.py +0 -0
  208. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_extensions.py +0 -0
  209. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_fact_extractor.py +0 -0
  210. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_governance.py +0 -0
  211. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_governance_spec_drift.py +0 -0
  212. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_graph_retriever.py +0 -0
  213. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_intent_classifier.py +0 -0
  214. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_json_parse.py +0 -0
  215. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_logging_compliance.py +0 -0
  216. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_memory_evolver.py +0 -0
  217. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_memory_updater.py +0 -0
  218. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_performance.py +0 -0
  219. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_recall_integration.py +0 -0
  220. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_sqlite_backend.py +0 -0
  221. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_sqlite_integration.py +0 -0
  222. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_storage_backend.py +0 -0
  223. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_temporal_graph.py +0 -0
  224. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_two_phase_e2e.py +0 -0
  225. {zettelforge-2.2.0 → zettelforge-2.3.0}/tests/test_typedb_client.py +0 -0
  226. {zettelforge-2.2.0 → zettelforge-2.3.0}/web/app.py +0 -0
  227. {zettelforge-2.2.0 → zettelforge-2.3.0}/web/auth.py +0 -0
@@ -33,8 +33,9 @@ jobs:
33
33
  runs-on: ubuntu-latest
34
34
  needs: lint
35
35
  strategy:
36
+ fail-fast: false
36
37
  matrix:
37
- python-version: ['3.12']
38
+ python-version: ['3.12', '3.13']
38
39
 
39
40
  steps:
40
41
  - uses: actions/checkout@v6
@@ -14,8 +14,8 @@ jobs:
14
14
  deploy:
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
- - uses: actions/checkout@v4
18
- - uses: actions/setup-python@v5
17
+ - uses: actions/checkout@v6
18
+ - uses: actions/setup-python@v6
19
19
  with:
20
20
  python-version: '3.12'
21
21
  - run: pip install mkdocs-material
@@ -2,6 +2,9 @@
2
2
  config.yaml
3
3
  config.yml
4
4
  .env
5
+ .env.*
6
+ *.key
7
+ *.pem
5
8
 
6
9
  # Local planning & task tracking (not committed)
7
10
  TODO.md
@@ -62,7 +65,7 @@ htmlcov/
62
65
  vectordb/
63
66
  .vector_memory.lance/
64
67
  .snapshots/
65
- archive/
68
+ /archive/
66
69
 
67
70
  # Data directories (runtime, not source)
68
71
  /data/
@@ -0,0 +1,42 @@
1
+ # Architecture
2
+
3
+ Visual diagram: [`docs/architecture-diagram.mmd`](docs/architecture-diagram.mmd)
4
+ Deep explanation: [`docs/explanation/architecture.md`](docs/explanation/architecture.md)
5
+
6
+ ## Storage
7
+
8
+ ZettelForge uses a `StorageBackend` ABC (33 methods) with pluggable
9
+ implementations. Set `ZETTELFORGE_BACKEND` to select.
10
+
11
+ - **SQLite** (default since v2.2.0): WAL mode, ACID, zero-config.
12
+ Notes, knowledge graph, and entity index in one database file.
13
+ - **LanceDB**: Vector index alongside SQLite. 768-dim embeddings
14
+ via fastembed (nomic-embed-text-v1.5-Q, ONNX, in-process).
15
+
16
+ ## Core Pipeline
17
+
18
+ 1. **Ingestion** — Governance validation → Note construction → Entity
19
+ extraction (regex fast-path + LLM) → Alias resolution → Storage
20
+ 2. **Enrichment** (background) — Causal triple extraction, memory
21
+ evolution (A-Mem neighbor refinement), HGAM consolidation
22
+ 3. **Retrieval** — Intent classification → Blended vector + graph
23
+ search → Temporal/causal boosting → Cross-encoder reranking
24
+ 4. **Synthesis** — RAG-as-Answer with quality validation
25
+
26
+ ## Extension Points
27
+
28
+ Extensions are optional packages discovered at startup via
29
+ `src/zettelforge/extensions.py`. If installed, they provide
30
+ alternative backends and integrations.
31
+
32
+ - Knowledge graph: TypeDB STIX 2.1 ontology with inference rules
33
+ - Authentication: Multi-tenant OAuth/JWT
34
+ - Integrations: OpenCTI bi-directional sync, Sigma rule generation
35
+
36
+ ## Why These Boundaries
37
+
38
+ TypeDB requires a running server. OpenCTI is a complex platform.
39
+ These dependencies should not be required to try ZettelForge.
40
+
41
+ The default backends are not toy implementations — they are
42
+ production-capable for single-user and small-team deployments.
@@ -6,6 +6,149 @@ Versioning follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.3.0] - 2026-04-17
10
+
11
+ Pluggable LLM provider infrastructure (RFC-002 Phase 1), MCP server
12
+ as a first-class Python module, PyPI discoverability refresh, SEO
13
+ foundations across the docs site, and a full docs-vs-code
14
+ reconciliation. All additions are backward-compatible; no existing
15
+ API changes. Supersedes the never-tagged 2.2.1 metadata patch —
16
+ its PyPI classifier / keyword / image-URL changes are folded in
17
+ below.
18
+
19
+ ### Added
20
+
21
+ - **Pluggable LLM provider infrastructure (RFC-002 Phase 1)** — new
22
+ `zettelforge.llm_providers` package with a `@runtime_checkable`
23
+ `LLMProvider` protocol, a thread-safe registry, and built-in
24
+ providers for `local` (llama-cpp-python), `ollama`, and `mock`.
25
+ The public `generate()` signature is unchanged; all 7 existing call
26
+ sites (`fact_extractor`, `memory_updater`, `synthesis_generator`,
27
+ `intent_classifier`, `note_constructor`, `entity_indexer`,
28
+ `memory_evolver`) keep working without modification. Third-party
29
+ providers can register via the `zettelforge.llm_providers`
30
+ entry-point group. `openai_compat` and `anthropic` providers land
31
+ in Phase 2 and Phase 3.
32
+ - **`LLMConfig` expanded** — new `api_key`, `timeout`, `max_retries`,
33
+ `fallback`, and `extra` fields. `api_key` supports `${ENV_VAR}`
34
+ references and is redacted from `repr()`. Sensitive keys inside
35
+ `extra` (matching `key|token|secret|password|credential|auth`) are
36
+ redacted as well. New env overrides: `ZETTELFORGE_LLM_API_KEY`,
37
+ `ZETTELFORGE_LLM_TIMEOUT`, `ZETTELFORGE_LLM_MAX_RETRIES`,
38
+ `ZETTELFORGE_LLM_FALLBACK`.
39
+ - **`LLMProviderConfigurationError`** — new exception surfaced for
40
+ non-recoverable provider setup problems (bad API key, missing
41
+ optional SDK) so `generate()` can distinguish "try the fallback"
42
+ from "stop and report".
43
+ - **`llm_client.reload()` helper** — clears the provider registry
44
+ and config cache so test suites and long-lived processes can
45
+ reconfigure the LLM backend without a process restart.
46
+ - **Hardened .gitignore** per GOV-023 — added `.env.*`, `*.key`,
47
+ `*.pem`.
48
+ - **MCP server as a first-class module** — `python -m zettelforge.mcp`
49
+ now works out of a `pip install zettelforge` with no git clone
50
+ required. New package `zettelforge.mcp` (with `server.py`,
51
+ `__main__.py`, and a console-script entry `zettelforge-mcp`).
52
+ The previous entry point at `web/mcp_server.py` is retained as a
53
+ thin backward-compat shim.
54
+ - **Console scripts** — `zettelforge` and `zettelforge-mcp` entry
55
+ points added to `pyproject.toml`.
56
+ - **How-to guides** — migration (`migrate-jsonl-to-sqlite.md`),
57
+ benchmark reproduction (`reproduce-benchmarks.md`), troubleshooting
58
+ (`troubleshoot.md`), and upgrade (`upgrade.md`). Linked from the
59
+ MkDocs nav.
60
+ - **Design and About sections in the docs nav** — RFC-001, RFC-002,
61
+ RFC-003 and the origin-story narrative are now discoverable from
62
+ `docs.threatrecall.ai`.
63
+ - **RFC-003 design proposal (docs only)** — read-path depth routing
64
+ with a deterministic Quality Gate plus System 1 / System 2 recall
65
+ paths. Ships with an adversarial-review artifact (4 blockers, 13
66
+ warnings). No runtime changes yet — implementation deferred.
67
+ - **Archive directory** — `docs/archive/` holds retired v1.0.0-alpha
68
+ snapshots (`SKILL.md`, `PACKAGE_SUMMARY.md`) with a README explaining
69
+ their provenance.
70
+ - **`llm_ner` configuration reference** — `docs/reference/configuration.md`
71
+ now documents `llm_ner.enabled` and the `ZETTELFORGE_LLM_NER_ENABLED`
72
+ environment override.
73
+ - **Docs SEO foundation** — per-page canonical URLs, OpenGraph and
74
+ Twitter-card metadata, and a `SoftwareApplication` JSON-LD block on
75
+ the home page via a `docs/overrides/main.html` theme override. The
76
+ `softwareVersion` value is sourced from `config.extra.version` in
77
+ `mkdocs.yml` so it stays in sync with releases.
78
+ - **PyPI classifier refresh** — added `Topic :: Security` (primary
79
+ filter security engineers use to browse PyPI) and
80
+ `Topic :: Software Development :: Libraries :: Python Modules`.
81
+ Existing `Topic :: Scientific/Engineering :: Artificial Intelligence`
82
+ retained. Development Status stays at `4 - Beta`.
83
+ - **PyPI keyword refresh** — swapped `agent-memory` → `agentic-memory`
84
+ (emerging category keyword) and `zettelkasten` → `llm-memory`
85
+ (direct intent match for Mem0/Graphiti discovery traffic). Still
86
+ 10 keywords total; within the PyPI display limit.
87
+
88
+ ### Changed
89
+
90
+ - **SECURITY.md** — contact updated to `contact@threatrecall.ai`,
91
+ supported-versions table refreshed to mark `2.3.x` as current and
92
+ `2.2.x` as the prior minor release; storage section refreshed to
93
+ reflect SQLite-by-default.
94
+ - **`docs/llms.txt`** — rewritten to match current reality (SQLite
95
+ default, 19 runtime entity types, correct GOV-003/007/011/012
96
+ descriptions, MCP invocation).
97
+ - **BENCHMARK_REPORT.md** — CTIBench ATE row updated (F1 = 0.146);
98
+ architecture summary reframed as SQLite + LanceDB default with
99
+ TypeDB as an extension; `ctibench_results.json` date bumped.
100
+ - **README** — above-fold rewritten (CTA row, keyword density,
101
+ PyPI-safe absolute-URL images). Pipeline step 1 entity count
102
+ corrected from "10 types" to the 19 types `EntityExtractor`
103
+ actually recognises.
104
+ - **README image paths** — `docs/assets/demo.gif` and
105
+ `docs/assets/zettelforge_architecture.svg` rewritten to absolute
106
+ `raw.githubusercontent.com` URLs so the PyPI long description
107
+ renders correctly (relative paths 404 on the PyPI CDN). Pinned to
108
+ the `master` ref; can be re-pinned to the `v2.3.0` tag in the
109
+ next release PR if PyPI-side stability matters.
110
+ - **`docs/superpowers/plans/` renamed to `docs/superpowers/research/`**
111
+ with a README making clear these are aspirational synthesis, not
112
+ roadmap commitments. The stray untracked `docs/plans/` directory
113
+ was removed.
114
+ - **Tutorials and governance-controls reference** — `last_updated`
115
+ and `version` metadata refreshed.
116
+ - **`zettelforge.ontology` exports** — `TypedEntityStore`,
117
+ `OntologyValidator`, `get_ontology_store`, `get_ontology_validator`
118
+ removed from the top-level `__all__` (still importable from
119
+ `zettelforge.ontology`). They are a parallel store not wired into
120
+ `MemoryManager`.
121
+ - **`observability.py` and `cache.py` headers** — annotated as
122
+ currently unwired; kept for future integration.
123
+ - **OCSF `_PRODUCT_VERSION`** — sourced from
124
+ `importlib.metadata.version("zettelforge")` instead of a hard-coded
125
+ string, so emitted OCSF events stop drifting when `__version__`
126
+ bumps.
127
+ - **OpenGraph `og:type`** — `website` on the home page, `article`
128
+ elsewhere (was unconditionally `article`).
129
+
130
+ ### Fixed
131
+
132
+ - **OllamaProvider host routing** — now instantiates
133
+ `ollama.Client(host=self._url)` so the configured URL actually
134
+ takes effect (previously the module-level `ollama.generate()` call
135
+ ignored per-instance host).
136
+ - **Provider registry race** — `register()` now checks and mutates
137
+ under the registry lock, closing a TOCTOU window on concurrent
138
+ provider registration.
139
+ - **MCP server lazy instantiation** — `MemoryManager` is now created
140
+ on first tool call rather than at server import time, so `--help`
141
+ and protocol-handshake tests don't pay the model-load cost.
142
+
143
+ ### Removed
144
+
145
+ - Six superseded branches that had already been squash-merged into
146
+ master — `feat/causal-chain-fix-and-demo-gif`,
147
+ `feat/entity-vocabulary-expansion`,
148
+ `feature/RFC-001-conversational-entity-extractor`,
149
+ `fix/intent-classifier-graph-weight`,
150
+ `fix/p0-production-blockers`, `feat/remember-evolve`.
151
+
9
152
  ## [2.2.0] - 2026-04-16
10
153
 
11
154
  SQLite default backend, causal chain retrieval, memory evolution, STIX taxonomy alignment, and community-first package cleanup.
@@ -1,23 +1,27 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zettelforge
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: ZettelForge: Agentic Memory System with vector search, knowledge graph, and synthesis
5
5
  Project-URL: Homepage, https://github.com/rolandpg/zettelforge
6
- Project-URL: Documentation, https://github.com/rolandpg/zettelforge/blob/main/docs/
6
+ Project-URL: Documentation, https://docs.threatrecall.ai
7
7
  Project-URL: Repository, https://github.com/rolandpg/zettelforge
8
8
  Project-URL: Issues, https://github.com/rolandpg/zettelforge/issues
9
+ Project-URL: Changelog, https://github.com/rolandpg/zettelforge/blob/master/CHANGELOG.md
9
10
  Author-email: Patrick Roland <patrick@groland.com>
10
11
  License-Expression: MIT
11
12
  License-File: LICENSE
12
- Keywords: agent-memory,ai-agent,cti,cybersecurity,knowledge-graph,mcp-server,rag,stix,threat-intelligence,zettelkasten
13
- Classifier: Development Status :: 3 - Alpha
13
+ Keywords: agentic-memory,ai-agent,cti,cybersecurity,knowledge-graph,llm-memory,mcp-server,rag,stix,threat-intelligence
14
+ Classifier: Development Status :: 4 - Beta
14
15
  Classifier: Intended Audience :: Developers
15
16
  Classifier: License :: OSI Approved :: MIT License
16
17
  Classifier: Programming Language :: Python :: 3
17
18
  Classifier: Programming Language :: Python :: 3.10
18
19
  Classifier: Programming Language :: Python :: 3.11
19
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
20
22
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Security
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
25
  Requires-Python: >=3.10
22
26
  Requires-Dist: fastembed>=0.8.0
23
27
  Requires-Dist: httpx>=0.25.0
@@ -50,28 +54,34 @@ Description-Content-Type: text/markdown
50
54
 
51
55
  **The only agentic memory system built for cyber threat intelligence.**
52
56
 
53
- Give your AI agents persistent memory with entity extraction, knowledge graphs, and STIX ontology -- no cloud, no API keys, works offline.
57
+ Persistent memory for AI agents and Claude Code — with CTI entity extraction, STIX knowledge graphs, threat-actor alias resolution, and offline-first RAG. MCP server included. No cloud, no API keys.
54
58
 
55
59
  [![PyPI](https://img.shields.io/pypi/v/zettelforge)](https://pypi.org/project/zettelforge/)
56
- [![Downloads](https://static.pepy.tech/badge/zettelforge)](https://pepy.tech/projects/zettelforge)
57
- [![Stars](https://img.shields.io/github/stars/rolandpg/zettelforge)](https://github.com/rolandpg/zettelforge/stargazers)
58
- [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://opensource.org/licenses/MIT)
60
+ [![Downloads/month](https://static.pepy.tech/personalized-badge/zettelforge?period=month&units=international_system&left_color=grey&right_color=blue&left_text=downloads%2Fmonth)](https://pepy.tech/projects/zettelforge)
59
61
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)
62
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://opensource.org/licenses/MIT)
60
63
  [![CI](https://github.com/rolandpg/zettelforge/actions/workflows/ci.yml/badge.svg)](https://github.com/rolandpg/zettelforge/actions)
61
- [![Contributors](https://img.shields.io/github/contributors/rolandpg/zettelforge)](https://github.com/rolandpg/zettelforge/graphs/contributors)
62
- [![Last Commit](https://img.shields.io/github/last-commit/rolandpg/zettelforge)](https://github.com/rolandpg/zettelforge/commits/master)
63
- [![SafeSkill](https://safeskill.dev/api/badge/rolandpg-zettelforge)](https://safeskill.dev/scan/rolandpg-zettelforge)
64
64
 
65
+ **[⭐ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted](https://threatrecall.ai)**
66
+
67
+ <p align="center">
68
+ <a href="https://www.buymeacoffee.com/xypher22pr0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me a Coffee" style="height: 60px !important;width: 217px !important;" ></a>
69
+ </p>
65
70
  <p align="center">
66
- <img src="docs/assets/demo.gif" width="720" alt="ZettelForge demo — CTI agentic memory in action">
71
+ <img src="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/demo.gif" width="720" alt="ZettelForge demo — CTI agentic memory in action">
67
72
  </p>
68
73
 
74
+ > If ZettelForge fits a CTI workflow you run, a star is the fastest signal that this category is worth continuing to invest in.
75
+
69
76
  ## Why ZettelForge?
70
77
 
71
78
  General-purpose memory systems don't understand threat intelligence. They can't tell APT28 from Fancy Bear, don't know that CVE-2024-3094 is the XZ Utils backdoor, and can't track how intelligence evolves across reports. When your agent forgets context between investigations, you end up re-reading the same reports and re-building the same mental models.
72
79
 
73
80
  ZettelForge was built from the ground up for analysts who think in threat graphs, not chat histories. It extracts CVEs, threat actors, IOCs, and MITRE ATT&CK techniques automatically, resolves aliases across naming conventions, builds a knowledge graph with causal relationships, and retrieves memories using intent-aware blended search -- all offline, with no API keys or cloud dependencies.
74
81
 
82
+ >"Memory augmentation closes 33% of the gap between small and large models on CTI tasks (CTI-REALM, Microsoft 2026)." [1]
83
+
84
+
75
85
  | Feature | ZettelForge | Mem0 | Graphiti | Cognee |
76
86
  |---------|------------|------|----------|--------|
77
87
  | CTI entity extraction (CVEs, actors, IOCs) | Yes | No | No | No |
@@ -83,6 +93,12 @@ ZettelForge was built from the ground up for analysts who think in threat graphs
83
93
  | OCSF audit logging | Yes | No | No | No |
84
94
  | MCP server (Claude Code) | Yes | No | No | No |
85
95
 
96
+ ## Data Pipeline
97
+ <p align="center">
98
+ <img src="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture.svg" width="720" alt="ZettelForge architecture — Extract, Graph, Embed, Recall pipeline">
99
+ </p>
100
+
101
+
86
102
  ## Features
87
103
 
88
104
  **Entity Extraction** -- Automatically identifies CVEs, threat actors, IOCs (IPs, domains, hashes, URLs, emails), MITRE ATT&CK techniques, campaigns, intrusion sets, tools, people, locations, and organizations. Regex + LLM NER with STIX 2.1 types throughout.
@@ -148,7 +164,7 @@ mm.remember(
148
164
 
149
165
  Every `remember()` call triggers a pipeline:
150
166
 
151
- 1. **Entity Extraction** -- regex + LLM NER identifies CVEs, actors, tools, campaigns, people, locations, orgs (10 types)
167
+ 1. **Entity Extraction** -- regex + LLM NER identifies CVEs, intrusion sets, threat actors, tools, campaigns, ATT&CK techniques, IOCs (IPv4, domain, URL, MD5/SHA1/SHA256, email), people, locations, organizations, events, activities, and temporal references (19 types)
152
168
  2. **Knowledge Graph Update** -- entities become nodes, co-occurrence becomes edges, LLM infers causal triples
153
169
  3. **Vector Embedding** -- 768-dim fastembed (ONNX, in-process, 7ms/embed) stored in LanceDB
154
170
  4. **Supersession Check** -- entity overlap detection marks stale notes as superseded
@@ -206,26 +222,6 @@ python examples/athf_bridge.py /path/to/hunts/
206
222
 
207
223
  See [examples/athf_bridge.py](examples/athf_bridge.py).
208
224
 
209
- ## Architecture
210
-
211
- ```
212
- ┌──────────────────────────────────────────────────────────────────────┐
213
- │ MemoryManager │
214
- │ remember() remember_with_extraction() recall() synthesize() │
215
- ├──────────┬───────────┬──────────────┬───────────┬────────────────────┤
216
- │ Note │ Fact │ Memory │ Blended │ Synthesis │
217
- │Constructor│ Extractor │ Updater │ Retriever │ Generator │
218
- │(enrich) │(Phase 1) │(Phase 2) │(vec+graph)│ (RAG) │
219
- ├──────────┴───────────┴──────────────┼───────────┴────────────────────┤
220
- │ Entity Indexer + Alias │ Intent Classifier │
221
- │ Resolver │ (factual/temporal/causal) │
222
- ├─────────────────────────────────────┼────────────────────────────────┤
223
- │ Knowledge Graph (SQLite) │ LanceDB (Vectors) │
224
- │ Entity nodes + edges │ 768-dim fastembed (ONNX) │
225
- │ Causal triple inference │ Zettelkasten notes │
226
- │ SQLite WAL (TypeDB via extension) │ IVF_PQ index │
227
- └─────────────────────────────────────┴────────────────────────────────┘
228
- ```
229
225
 
230
226
  ## Extensions
231
227
 
@@ -272,6 +268,12 @@ MIT -- See [LICENSE](LICENSE).
272
268
 
273
269
  **Made by Patrick Roland**.
274
270
 
271
+ ## Support the Project
272
+
273
+ ZettelForge is MIT-licensed. If it's useful in your workflow and you'd like to help keep it maintained:
274
+
275
+ <a href="https://www.buymeacoffee.com/xypher22pr0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me a Coffee" style="height: 40px !important;width: 145px !important;" ></a>
276
+
275
277
  ## Acknowledgments
276
278
 
277
279
  - Inspired by [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) and [A-Mem](https://arxiv.org/abs/2602.10715) (NeurIPS 2025)
@@ -279,3 +281,5 @@ MIT -- See [LICENSE](LICENSE).
279
281
  - STIX 2.1 schema informed by [typedb-cti](https://github.com/typedb-osi/typedb-cti)
280
282
  - Benchmarked against [LOCOMO](https://snap-research.github.io/locomo/) (ACL 2024) and [CTIBench](https://arxiv.org/abs/2406.07599) (NeurIPS 2024)
281
283
  - [LanceDB](https://lancedb.com) | [fastembed](https://github.com/qdrant/fastembed) | [Pydantic](https://pydantic.dev) | [TypeDB](https://typedb.com)
284
+
285
+ [1]: https://www.microsoft.com/en-us/security/blog/2026/03/20/cti-realm-a-new-benchmark-for-end-to-end-detection-rule-generation-with-ai-agents/
@@ -2,28 +2,34 @@
2
2
 
3
3
  **The only agentic memory system built for cyber threat intelligence.**
4
4
 
5
- Give your AI agents persistent memory with entity extraction, knowledge graphs, and STIX ontology -- no cloud, no API keys, works offline.
5
+ Persistent memory for AI agents and Claude Code — with CTI entity extraction, STIX knowledge graphs, threat-actor alias resolution, and offline-first RAG. MCP server included. No cloud, no API keys.
6
6
 
7
7
  [![PyPI](https://img.shields.io/pypi/v/zettelforge)](https://pypi.org/project/zettelforge/)
8
- [![Downloads](https://static.pepy.tech/badge/zettelforge)](https://pepy.tech/projects/zettelforge)
9
- [![Stars](https://img.shields.io/github/stars/rolandpg/zettelforge)](https://github.com/rolandpg/zettelforge/stargazers)
10
- [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://opensource.org/licenses/MIT)
8
+ [![Downloads/month](https://static.pepy.tech/personalized-badge/zettelforge?period=month&units=international_system&left_color=grey&right_color=blue&left_text=downloads%2Fmonth)](https://pepy.tech/projects/zettelforge)
11
9
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://opensource.org/licenses/MIT)
12
11
  [![CI](https://github.com/rolandpg/zettelforge/actions/workflows/ci.yml/badge.svg)](https://github.com/rolandpg/zettelforge/actions)
13
- [![Contributors](https://img.shields.io/github/contributors/rolandpg/zettelforge)](https://github.com/rolandpg/zettelforge/graphs/contributors)
14
- [![Last Commit](https://img.shields.io/github/last-commit/rolandpg/zettelforge)](https://github.com/rolandpg/zettelforge/commits/master)
15
- [![SafeSkill](https://safeskill.dev/api/badge/rolandpg-zettelforge)](https://safeskill.dev/scan/rolandpg-zettelforge)
16
12
 
13
+ **[⭐ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted](https://threatrecall.ai)**
14
+
15
+ <p align="center">
16
+ <a href="https://www.buymeacoffee.com/xypher22pr0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me a Coffee" style="height: 60px !important;width: 217px !important;" ></a>
17
+ </p>
17
18
  <p align="center">
18
- <img src="docs/assets/demo.gif" width="720" alt="ZettelForge demo — CTI agentic memory in action">
19
+ <img src="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/demo.gif" width="720" alt="ZettelForge demo — CTI agentic memory in action">
19
20
  </p>
20
21
 
22
+ > If ZettelForge fits a CTI workflow you run, a star is the fastest signal that this category is worth continuing to invest in.
23
+
21
24
  ## Why ZettelForge?
22
25
 
23
26
  General-purpose memory systems don't understand threat intelligence. They can't tell APT28 from Fancy Bear, don't know that CVE-2024-3094 is the XZ Utils backdoor, and can't track how intelligence evolves across reports. When your agent forgets context between investigations, you end up re-reading the same reports and re-building the same mental models.
24
27
 
25
28
  ZettelForge was built from the ground up for analysts who think in threat graphs, not chat histories. It extracts CVEs, threat actors, IOCs, and MITRE ATT&CK techniques automatically, resolves aliases across naming conventions, builds a knowledge graph with causal relationships, and retrieves memories using intent-aware blended search -- all offline, with no API keys or cloud dependencies.
26
29
 
30
+ >"Memory augmentation closes 33% of the gap between small and large models on CTI tasks (CTI-REALM, Microsoft 2026)." [1]
31
+
32
+
27
33
  | Feature | ZettelForge | Mem0 | Graphiti | Cognee |
28
34
  |---------|------------|------|----------|--------|
29
35
  | CTI entity extraction (CVEs, actors, IOCs) | Yes | No | No | No |
@@ -35,6 +41,12 @@ ZettelForge was built from the ground up for analysts who think in threat graphs
35
41
  | OCSF audit logging | Yes | No | No | No |
36
42
  | MCP server (Claude Code) | Yes | No | No | No |
37
43
 
44
+ ## Data Pipeline
45
+ <p align="center">
46
+ <img src="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture.svg" width="720" alt="ZettelForge architecture — Extract, Graph, Embed, Recall pipeline">
47
+ </p>
48
+
49
+
38
50
  ## Features
39
51
 
40
52
  **Entity Extraction** -- Automatically identifies CVEs, threat actors, IOCs (IPs, domains, hashes, URLs, emails), MITRE ATT&CK techniques, campaigns, intrusion sets, tools, people, locations, and organizations. Regex + LLM NER with STIX 2.1 types throughout.
@@ -100,7 +112,7 @@ mm.remember(
100
112
 
101
113
  Every `remember()` call triggers a pipeline:
102
114
 
103
- 1. **Entity Extraction** -- regex + LLM NER identifies CVEs, actors, tools, campaigns, people, locations, orgs (10 types)
115
+ 1. **Entity Extraction** -- regex + LLM NER identifies CVEs, intrusion sets, threat actors, tools, campaigns, ATT&CK techniques, IOCs (IPv4, domain, URL, MD5/SHA1/SHA256, email), people, locations, organizations, events, activities, and temporal references (19 types)
104
116
  2. **Knowledge Graph Update** -- entities become nodes, co-occurrence becomes edges, LLM infers causal triples
105
117
  3. **Vector Embedding** -- 768-dim fastembed (ONNX, in-process, 7ms/embed) stored in LanceDB
106
118
  4. **Supersession Check** -- entity overlap detection marks stale notes as superseded
@@ -158,26 +170,6 @@ python examples/athf_bridge.py /path/to/hunts/
158
170
 
159
171
  See [examples/athf_bridge.py](examples/athf_bridge.py).
160
172
 
161
- ## Architecture
162
-
163
- ```
164
- ┌──────────────────────────────────────────────────────────────────────┐
165
- │ MemoryManager │
166
- │ remember() remember_with_extraction() recall() synthesize() │
167
- ├──────────┬───────────┬──────────────┬───────────┬────────────────────┤
168
- │ Note │ Fact │ Memory │ Blended │ Synthesis │
169
- │Constructor│ Extractor │ Updater │ Retriever │ Generator │
170
- │(enrich) │(Phase 1) │(Phase 2) │(vec+graph)│ (RAG) │
171
- ├──────────┴───────────┴──────────────┼───────────┴────────────────────┤
172
- │ Entity Indexer + Alias │ Intent Classifier │
173
- │ Resolver │ (factual/temporal/causal) │
174
- ├─────────────────────────────────────┼────────────────────────────────┤
175
- │ Knowledge Graph (SQLite) │ LanceDB (Vectors) │
176
- │ Entity nodes + edges │ 768-dim fastembed (ONNX) │
177
- │ Causal triple inference │ Zettelkasten notes │
178
- │ SQLite WAL (TypeDB via extension) │ IVF_PQ index │
179
- └─────────────────────────────────────┴────────────────────────────────┘
180
- ```
181
173
 
182
174
  ## Extensions
183
175
 
@@ -224,6 +216,12 @@ MIT -- See [LICENSE](LICENSE).
224
216
 
225
217
  **Made by Patrick Roland**.
226
218
 
219
+ ## Support the Project
220
+
221
+ ZettelForge is MIT-licensed. If it's useful in your workflow and you'd like to help keep it maintained:
222
+
223
+ <a href="https://www.buymeacoffee.com/xypher22pr0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me a Coffee" style="height: 40px !important;width: 145px !important;" ></a>
224
+
227
225
  ## Acknowledgments
228
226
 
229
227
  - Inspired by [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) and [A-Mem](https://arxiv.org/abs/2602.10715) (NeurIPS 2025)
@@ -231,3 +229,5 @@ MIT -- See [LICENSE](LICENSE).
231
229
  - STIX 2.1 schema informed by [typedb-cti](https://github.com/typedb-osi/typedb-cti)
232
230
  - Benchmarked against [LOCOMO](https://snap-research.github.io/locomo/) (ACL 2024) and [CTIBench](https://arxiv.org/abs/2406.07599) (NeurIPS 2024)
233
231
  - [LanceDB](https://lancedb.com) | [fastembed](https://github.com/qdrant/fastembed) | [Pydantic](https://pydantic.dev) | [TypeDB](https://typedb.com)
232
+
233
+ [1]: https://www.microsoft.com/en-us/security/blog/2026/03/20/cti-realm-a-new-benchmark-for-end-to-end-detection-rule-generation-with-ai-agents/
@@ -6,7 +6,7 @@
6
6
 
7
7
  Report security issues by email to:
8
8
 
9
- **security@zettelforge.dev**
9
+ **contact@threatrecall.ai**
10
10
 
11
11
  Include in your report:
12
12
  - A description of the vulnerability and its potential impact
@@ -39,9 +39,9 @@ backported to the prior minor release.
39
39
 
40
40
  | Version | Supported |
41
41
  |---|---|
42
- | 2.1.x (current) | Yes — active security support |
43
- | 2.0.x | Critical fixes only, for 60 days after 2.1.0 release |
44
- | < 2.0 | No — upgrade required |
42
+ | 2.3.x (current) | Yes — active security support |
43
+ | 2.2.x | Critical fixes only, for 60 days after 2.3.0 release |
44
+ | < 2.2 | No — upgrade required |
45
45
 
46
46
  ---
47
47
 
@@ -53,8 +53,9 @@ The following components are covered by this policy:
53
53
 
54
54
  - **Memory pipeline** — `remember()`, `recall()`, `synthesize()`, and
55
55
  the two-phase extraction pipeline
56
- - **Storage layer** — JSONL notes store, LanceDB vector index, entity
57
- index, knowledge graph JSONL
56
+ - **Storage layer** — SQLite backend (notes, knowledge graph, entity index)
57
+ and the LanceDB vector index. Legacy JSONL paths still present for
58
+ migration are also in scope.
58
59
  - **MCP server** — all tool handlers exposed to Claude Code and other
59
60
  MCP clients
60
61
  - **REST API** — all FastAPI endpoints in `src/zettelforge/server.py`
@@ -83,11 +84,16 @@ The following components are covered by this policy:
83
84
 
84
85
  ### Data at Rest
85
86
 
86
- - Notes are stored as JSONL on local disk. No encryption at rest is
87
- applied by ZettelForge itself encrypt the filesystem or volume at
88
- the OS level for sensitive deployments.
89
- - LanceDB vector index files are stored in the configured data directory
90
- and carry the same recommendation.
87
+ - Notes, the knowledge graph, and the entity index are stored in a local
88
+ SQLite database (WAL mode) under the configured data directory. No
89
+ encryption at rest is applied by ZettelForge itself — encrypt the
90
+ filesystem or volume at the OS level for sensitive deployments.
91
+ - LanceDB vector index files live alongside the SQLite database and
92
+ carry the same recommendation.
93
+ - Legacy v2.1.x deployments that still use JSONL (`notes.jsonl`,
94
+ `kg_nodes.jsonl`, `kg_edges.jsonl`, `entity_index.json`) should run
95
+ `scripts/migrate_jsonl_to_sqlite.py` — the JSONL paths are no longer
96
+ the default but remain supported as a migration input.
91
97
 
92
98
  ### Injection Defenses
93
99