zettelforge 2.2.0__tar.gz → 2.4.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 (290) hide show
  1. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/workflows/ci.yml +2 -1
  2. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/workflows/docs.yml +2 -2
  3. {zettelforge-2.2.0 → zettelforge-2.4.0}/.gitignore +4 -1
  4. zettelforge-2.4.0/ARCHITECTURE.md +42 -0
  5. {zettelforge-2.2.0 → zettelforge-2.4.0}/CHANGELOG.md +198 -0
  6. {zettelforge-2.2.0 → zettelforge-2.4.0}/CODE_OF_CONDUCT.md +1 -1
  7. {zettelforge-2.2.0 → zettelforge-2.4.0}/PKG-INFO +75 -33
  8. {zettelforge-2.2.0 → zettelforge-2.4.0}/README.md +64 -29
  9. {zettelforge-2.2.0 → zettelforge-2.4.0}/SECURITY.md +38 -11
  10. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/BENCHMARK_REPORT.md +45 -19
  11. {zettelforge-2.2.0 → zettelforge-2.4.0}/config.default.yaml +49 -17
  12. zettelforge-2.4.0/docs/.well-known/security.txt +10 -0
  13. zettelforge-2.4.0/docs/architecture-diagram.mmd +202 -0
  14. zettelforge-2.4.0/docs/archive/README.md +11 -0
  15. zettelforge-2.4.0/docs/assets/ZettelForge_Architecture.mmd +185 -0
  16. zettelforge-2.4.0/docs/assets/architecture-overview.mmd +57 -0
  17. zettelforge-2.4.0/docs/assets/architecture-read-path.mmd +140 -0
  18. zettelforge-2.4.0/docs/assets/architecture-write-path.mmd +122 -0
  19. zettelforge-2.4.0/docs/assets/favicon-16.png +0 -0
  20. zettelforge-2.4.0/docs/assets/favicon-32.png +0 -0
  21. zettelforge-2.4.0/docs/assets/favicon-512.png +0 -0
  22. zettelforge-2.4.0/docs/assets/favicon-64.png +0 -0
  23. zettelforge-2.4.0/docs/assets/favicon-apple-touch.png +0 -0
  24. zettelforge-2.4.0/docs/assets/favicon.svg +33 -0
  25. zettelforge-2.4.0/docs/assets/logo.svg +46 -0
  26. zettelforge-2.4.0/docs/assets/social-preview.png +0 -0
  27. zettelforge-2.4.0/docs/assets/threatrecall-lockup-monogram.svg +41 -0
  28. zettelforge-2.4.0/docs/assets/threatrecall-lockup.svg +39 -0
  29. zettelforge-2.4.0/docs/assets/threatrecall-logo-flat.svg +29 -0
  30. zettelforge-2.4.0/docs/assets/zettelforge_architecture-light.svg +105 -0
  31. zettelforge-2.4.0/docs/assets/zettelforge_architecture.svg +105 -0
  32. zettelforge-2.4.0/docs/brand/brandIdentity.md +266 -0
  33. zettelforge-2.4.0/docs/brand/colors_and_type.css +286 -0
  34. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/explanation/architecture.md +1 -1
  35. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/explanation/stix-in-zettelforge.md +1 -1
  36. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/integrate-llm-agent.md +1 -1
  37. zettelforge-2.4.0/docs/how-to/migrate-jsonl-to-sqlite.md +114 -0
  38. zettelforge-2.4.0/docs/how-to/reproduce-benchmarks.md +120 -0
  39. zettelforge-2.4.0/docs/how-to/troubleshoot.md +180 -0
  40. zettelforge-2.4.0/docs/how-to/upgrade.md +94 -0
  41. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/index.md +4 -4
  42. zettelforge-2.4.0/docs/llms.txt +64 -0
  43. zettelforge-2.4.0/docs/narrative/2026-04-16-the-memory-problem.md +86 -0
  44. zettelforge-2.4.0/docs/overrides/main.html +82 -0
  45. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/reference/configuration.md +39 -10
  46. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/reference/governance-controls.md +2 -2
  47. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/reference/memory-manager-api.md +1 -1
  48. zettelforge-2.4.0/docs/rfcs/RFC-001-conversational-entity-extractor.md +356 -0
  49. zettelforge-2.4.0/docs/rfcs/RFC-002-universal-llm-provider.md +883 -0
  50. zettelforge-2.4.0/docs/rfcs/RFC-003-adversarial-review.md +393 -0
  51. zettelforge-2.4.0/docs/rfcs/RFC-003-read-path-depth-routing.md +936 -0
  52. zettelforge-2.4.0/docs/stylesheets/brand-tokens.css +158 -0
  53. zettelforge-2.4.0/docs/stylesheets/extra.css +70 -0
  54. zettelforge-2.4.0/docs/stylesheets/fonts/Neuropol.otf +0 -0
  55. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-15-causal-graph.md +36 -0
  56. zettelforge-2.4.0/docs/superpowers/research/2026-04-15-format-stability.md +1029 -0
  57. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-15-memory-evolution.md +41 -1
  58. zettelforge-2.4.0/docs/superpowers/research/2026-04-15-merge-consolidation.md +372 -0
  59. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-15-persistence-semantics.md +50 -0
  60. zettelforge-2.4.0/docs/superpowers/research/2026-04-17-test-suite-audit.md +178 -0
  61. zettelforge-2.4.0/docs/superpowers/research/README.md +40 -0
  62. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/superpowers/specs/2026-04-15-p1-features-prd.md +197 -29
  63. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/tutorials/01-quickstart.md +3 -3
  64. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/tutorials/02-first-cti-report.md +2 -2
  65. {zettelforge-2.2.0 → zettelforge-2.4.0}/mkdocs.yml +32 -2
  66. {zettelforge-2.2.0 → zettelforge-2.4.0}/pyproject.toml +16 -4
  67. zettelforge-2.4.0/server.json +21 -0
  68. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/__init__.py +14 -10
  69. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/backend_factory.py +21 -0
  70. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/cache.py +7 -3
  71. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/config.py +117 -6
  72. zettelforge-2.4.0/src/zettelforge/detection/__init__.py +24 -0
  73. zettelforge-2.4.0/src/zettelforge/detection/base.py +63 -0
  74. zettelforge-2.4.0/src/zettelforge/detection/consumers.py +77 -0
  75. zettelforge-2.4.0/src/zettelforge/detection/explainer.py +320 -0
  76. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/entity_indexer.py +11 -3
  77. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/integrations/langchain_retriever.py +3 -6
  78. zettelforge-2.4.0/src/zettelforge/llm_client.py +287 -0
  79. zettelforge-2.4.0/src/zettelforge/llm_providers/__init__.py +84 -0
  80. zettelforge-2.4.0/src/zettelforge/llm_providers/base.py +59 -0
  81. zettelforge-2.4.0/src/zettelforge/llm_providers/local_provider.py +96 -0
  82. zettelforge-2.4.0/src/zettelforge/llm_providers/mock_provider.py +50 -0
  83. zettelforge-2.4.0/src/zettelforge/llm_providers/ollama_provider.py +56 -0
  84. zettelforge-2.4.0/src/zettelforge/llm_providers/registry.py +76 -0
  85. zettelforge-2.4.0/src/zettelforge/mcp/__init__.py +34 -0
  86. zettelforge-2.4.0/src/zettelforge/mcp/__main__.py +11 -0
  87. zettelforge-2.2.0/web/mcp_server.py → zettelforge-2.4.0/src/zettelforge/mcp/server.py +30 -40
  88. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/memory_manager.py +107 -3
  89. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/observability.py +8 -3
  90. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/ocsf.py +15 -1
  91. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/ontology.py +129 -4
  92. zettelforge-2.4.0/src/zettelforge/sigma/__init__.py +31 -0
  93. zettelforge-2.4.0/src/zettelforge/sigma/cli.py +123 -0
  94. zettelforge-2.4.0/src/zettelforge/sigma/entities.py +249 -0
  95. zettelforge-2.4.0/src/zettelforge/sigma/ingest.py +234 -0
  96. zettelforge-2.4.0/src/zettelforge/sigma/parser.py +148 -0
  97. zettelforge-2.4.0/src/zettelforge/sigma/schemas/NOTICE.md +10 -0
  98. zettelforge-2.4.0/src/zettelforge/sigma/schemas/__init__.py +1 -0
  99. zettelforge-2.4.0/src/zettelforge/sigma/schemas/sigma-correlation-rules-schema.json +326 -0
  100. zettelforge-2.4.0/src/zettelforge/sigma/schemas/sigma-detection-rule-schema.json +247 -0
  101. zettelforge-2.4.0/src/zettelforge/sigma/schemas/sigma-filters-schema.json +101 -0
  102. zettelforge-2.4.0/src/zettelforge/sigma/tags.py +86 -0
  103. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/sqlite_backend.py +157 -125
  104. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/vector_retriever.py +12 -2
  105. zettelforge-2.4.0/src/zettelforge/yara/__init__.py +27 -0
  106. zettelforge-2.4.0/src/zettelforge/yara/cccs_metadata.py +258 -0
  107. zettelforge-2.4.0/src/zettelforge/yara/cli.py +177 -0
  108. zettelforge-2.4.0/src/zettelforge/yara/entities.py +269 -0
  109. zettelforge-2.4.0/src/zettelforge/yara/ingest.py +327 -0
  110. zettelforge-2.4.0/src/zettelforge/yara/parser.py +110 -0
  111. zettelforge-2.4.0/src/zettelforge/yara/schemas/CCCS_YARA.yml +306 -0
  112. zettelforge-2.4.0/src/zettelforge/yara/schemas/CCCS_YARA_values.yml +160 -0
  113. zettelforge-2.4.0/src/zettelforge/yara/schemas/NOTICE.md +11 -0
  114. zettelforge-2.4.0/src/zettelforge/yara/schemas/__init__.py +1 -0
  115. zettelforge-2.4.0/src/zettelforge/yara/tags.py +74 -0
  116. zettelforge-2.4.0/tests/fixtures/sigma/cloud_example.yml +20 -0
  117. zettelforge-2.4.0/tests/fixtures/sigma/correlation_example.yml +14 -0
  118. zettelforge-2.4.0/tests/fixtures/sigma/process_creation_example.yml +17 -0
  119. zettelforge-2.4.0/tests/fixtures/sigma/tagged_example.yml +30 -0
  120. zettelforge-2.4.0/tests/fixtures/yara/malware_hash.yar +19 -0
  121. zettelforge-2.4.0/tests/fixtures/yara/technique_loader.yar +23 -0
  122. zettelforge-2.4.0/tests/fixtures/yara/webshell.yar +19 -0
  123. zettelforge-2.4.0/tests/test_causal_extraction.py +102 -0
  124. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_conversational_entities.py +50 -11
  125. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_core.py +6 -5
  126. zettelforge-2.4.0/tests/test_detection_explainer.py +328 -0
  127. zettelforge-2.4.0/tests/test_detection_rule_entities.py +104 -0
  128. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_langchain_retriever.py +18 -7
  129. zettelforge-2.4.0/tests/test_llm_client.py +158 -0
  130. zettelforge-2.4.0/tests/test_llm_providers.py +318 -0
  131. zettelforge-2.4.0/tests/test_mcp_server.py +139 -0
  132. zettelforge-2.4.0/tests/test_sigma_entities.py +205 -0
  133. zettelforge-2.4.0/tests/test_sigma_ingest.py +212 -0
  134. zettelforge-2.4.0/tests/test_sigma_parser.py +125 -0
  135. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_two_phase_e2e.py +18 -15
  136. zettelforge-2.4.0/tests/test_yara_entities.py +170 -0
  137. zettelforge-2.4.0/tests/test_yara_ingest.py +126 -0
  138. zettelforge-2.4.0/tests/test_yara_parser.py +126 -0
  139. zettelforge-2.4.0/web/mcp_server.py +18 -0
  140. zettelforge-2.2.0/ARCHITECTURE.md +0 -36
  141. zettelforge-2.2.0/docs/assets/logo.svg +0 -3
  142. zettelforge-2.2.0/docs/assets/social-preview.png +0 -0
  143. zettelforge-2.2.0/docs/assets/threatrecall-logo.svg +0 -22
  144. zettelforge-2.2.0/docs/assets/threatrecall-mark.svg +0 -12
  145. zettelforge-2.2.0/docs/llms.txt +0 -50
  146. zettelforge-2.2.0/docs/rfcs/RFC-001-conversational-entity-extractor.md +0 -113
  147. zettelforge-2.2.0/docs/stylesheets/extra.css +0 -10
  148. zettelforge-2.2.0/src/zettelforge/llm_client.py +0 -150
  149. zettelforge-2.2.0/tests/test_causal_extraction.py +0 -91
  150. zettelforge-2.2.0/tests/test_llm_client.py +0 -76
  151. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/CODEOWNERS +0 -0
  152. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  153. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  154. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/SECURITY.md +0 -0
  155. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/dependabot.yml +0 -0
  156. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/pull_request_template.md +0 -0
  157. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/workflows/publish.yml +0 -0
  158. {zettelforge-2.2.0 → zettelforge-2.4.0}/.github/workflows/snyk-security.yml +0 -0
  159. {zettelforge-2.2.0 → zettelforge-2.4.0}/CODEOWNERS +0 -0
  160. {zettelforge-2.2.0 → zettelforge-2.4.0}/CONTRIBUTING.md +0 -0
  161. {zettelforge-2.2.0 → zettelforge-2.4.0}/Dockerfile +0 -0
  162. {zettelforge-2.2.0 → zettelforge-2.4.0}/GOVERNANCE.md +0 -0
  163. {zettelforge-2.2.0 → zettelforge-2.4.0}/LICENSE +0 -0
  164. {zettelforge-2.2.0 → zettelforge-2.4.0}/MANIFEST.in +0 -0
  165. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/LOCOMO_BENCHMARK_COMPARISON.md +0 -0
  166. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/auto_ralph.py +0 -0
  167. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/benchmark_harness.py +0 -0
  168. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/cti_benchmark_v2.py +0 -0
  169. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/cti_retrieval_benchmark.py +0 -0
  170. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/cti_retrieval_results.json +0 -0
  171. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/cti_v2_results.json +0 -0
  172. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/ctibench_benchmark.py +0 -0
  173. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/ctibench_results.json +0 -0
  174. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/dataset.json +0 -0
  175. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/enterprise-attack.json +0 -0
  176. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/evolve_benchmark.py +0 -0
  177. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/evolve_results.json +0 -0
  178. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/graph_test.py +0 -0
  179. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/locomo_benchmark.py +0 -0
  180. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/locomo_results.json +0 -0
  181. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/locomo_results_v1.3.0_baseline.json +0 -0
  182. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/memoryagentbench.py +0 -0
  183. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/memoryagentbench_results.json +0 -0
  184. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/mempalace_benchmark.py +0 -0
  185. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/mempalace_results.json +0 -0
  186. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/naive_memory.py +0 -0
  187. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/opencti_benchmark.py +0 -0
  188. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/ragas_benchmark.py +0 -0
  189. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/ragas_cti_results.json +0 -0
  190. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/ragas_results.json +0 -0
  191. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/results/benchmark_report.md +0 -0
  192. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/results/ralph_optimization_log.json +0 -0
  193. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/scale_benchmark.py +0 -0
  194. {zettelforge-2.2.0 → zettelforge-2.4.0}/benchmarks/scale_results.json +0 -0
  195. {zettelforge-2.2.0 → zettelforge-2.4.0}/config.example.yaml +0 -0
  196. {zettelforge-2.2.0 → zettelforge-2.4.0}/docker/docker-compose.yml +0 -0
  197. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/CNAME +0 -0
  198. {zettelforge-2.2.0 → zettelforge-2.4.0/docs/archive}/PACKAGE_SUMMARY.md +0 -0
  199. {zettelforge-2.2.0 → zettelforge-2.4.0/docs/archive}/SKILL.md +0 -0
  200. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/assets/demo.gif +0 -0
  201. /zettelforge-2.2.0/docs/assets/favicon.svg → /zettelforge-2.4.0/docs/assets/favicon-old.svg +0 -0
  202. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/assets/threatrecall-logo-philosophy.md +0 -0
  203. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/assets/threatrecall-logo.png +0 -0
  204. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/assets/threatrecall-mark.png +0 -0
  205. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/explanation/epistemic-tiers.md +0 -0
  206. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/explanation/two-phase-pipeline.md +0 -0
  207. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/explanation/zettelkasten-philosophy.md +0 -0
  208. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/configure-lancedb.md +0 -0
  209. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/configure-opencti.md +0 -0
  210. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/configure-typedb.md +0 -0
  211. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/ingest-news-report.md +0 -0
  212. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/query-apt-tools.md +0 -0
  213. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/resolve-aliases.md +0 -0
  214. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/run-temporal-query.md +0 -0
  215. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/how-to/store-threat-actor.md +0 -0
  216. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/reference/retrieval-policies.md +0 -0
  217. {zettelforge-2.2.0 → zettelforge-2.4.0}/docs/reference/stix-schema.md +0 -0
  218. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-09-ctibench-ragas-benchmarks.md +0 -0
  219. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-09-fastembed-local-embeddings.md +0 -0
  220. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-09-hybrid-typedb-lancedb-architecture.md +0 -0
  221. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-09-local-llm-llama-cpp.md +0 -0
  222. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-15-anti-aversion-cleanup.md +0 -0
  223. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-15-ctibench-ate-fix.md +0 -0
  224. {zettelforge-2.2.0/docs/superpowers/plans → zettelforge-2.4.0/docs/superpowers/research}/2026-04-15-sqlite-migration.md +0 -0
  225. {zettelforge-2.2.0 → zettelforge-2.4.0}/examples/athf_bridge.py +0 -0
  226. {zettelforge-2.2.0 → zettelforge-2.4.0}/examples/mcp_claude_code.md +0 -0
  227. {zettelforge-2.2.0 → zettelforge-2.4.0}/examples/quickstart.py +0 -0
  228. {zettelforge-2.2.0 → zettelforge-2.4.0}/governance/controls.yaml +0 -0
  229. {zettelforge-2.2.0 → zettelforge-2.4.0}/scripts/migrate_jsonl_to_sqlite.py +0 -0
  230. {zettelforge-2.2.0 → zettelforge-2.4.0}/scripts/rebuild_index.py +0 -0
  231. {zettelforge-2.2.0 → zettelforge-2.4.0}/scripts/record-demo.sh +0 -0
  232. {zettelforge-2.2.0 → zettelforge-2.4.0}/scripts/typedb-setup.sh +0 -0
  233. {zettelforge-2.2.0 → zettelforge-2.4.0}/scripts/zettelforge-rebuild.service +0 -0
  234. {zettelforge-2.2.0 → zettelforge-2.4.0}/scripts/zettelforge-rebuild.timer +0 -0
  235. {zettelforge-2.2.0 → zettelforge-2.4.0}/skills/claude-code-skill.md +0 -0
  236. {zettelforge-2.2.0 → zettelforge-2.4.0}/skills/openclaw-skill.md +0 -0
  237. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/__main__.py +0 -0
  238. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/alias_resolver.py +0 -0
  239. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/blended_retriever.py +0 -0
  240. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/consolidation.py +0 -0
  241. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/demo.py +0 -0
  242. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/edition.py +0 -0
  243. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/extensions.py +0 -0
  244. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/fact_extractor.py +0 -0
  245. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/governance_validator.py +0 -0
  246. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/graph_retriever.py +0 -0
  247. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/integrations/__init__.py +0 -0
  248. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/intent_classifier.py +0 -0
  249. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/json_parse.py +0 -0
  250. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/knowledge_graph.py +0 -0
  251. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/log.py +0 -0
  252. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/memory_evolver.py +0 -0
  253. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/memory_store.py +0 -0
  254. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/memory_updater.py +0 -0
  255. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/note_constructor.py +0 -0
  256. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/note_schema.py +0 -0
  257. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/retry.py +0 -0
  258. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/storage_backend.py +0 -0
  259. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/synthesis_generator.py +0 -0
  260. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/synthesis_validator.py +0 -0
  261. {zettelforge-2.2.0 → zettelforge-2.4.0}/src/zettelforge/vector_memory.py +0 -0
  262. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/__init__.py +0 -0
  263. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/benchmark_scale.py +0 -0
  264. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/conftest.py +0 -0
  265. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_basic.py +0 -0
  266. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_blended_retriever.py +0 -0
  267. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_config.py +0 -0
  268. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_consolidation.py +0 -0
  269. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_cti_integration.py +0 -0
  270. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_edition.py +0 -0
  271. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_embedding.py +0 -0
  272. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_extensions.py +0 -0
  273. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_fact_extractor.py +0 -0
  274. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_governance.py +0 -0
  275. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_governance_spec_drift.py +0 -0
  276. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_graph_retriever.py +0 -0
  277. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_intent_classifier.py +0 -0
  278. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_json_parse.py +0 -0
  279. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_logging_compliance.py +0 -0
  280. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_memory_evolver.py +0 -0
  281. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_memory_updater.py +0 -0
  282. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_performance.py +0 -0
  283. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_recall_integration.py +0 -0
  284. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_sqlite_backend.py +0 -0
  285. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_sqlite_integration.py +0 -0
  286. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_storage_backend.py +0 -0
  287. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_temporal_graph.py +0 -0
  288. {zettelforge-2.2.0 → zettelforge-2.4.0}/tests/test_typedb_client.py +0 -0
  289. {zettelforge-2.2.0 → zettelforge-2.4.0}/web/app.py +0 -0
  290. {zettelforge-2.2.0 → zettelforge-2.4.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,204 @@ Versioning follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.4.0] - 2026-04-19
10
+
11
+ Detection-rules-as-memory, MCP Registry publication, SQLite concurrency
12
+ hardening, and a full test-suite hygiene pass.
13
+
14
+ ### Added
15
+
16
+ - **Detection rules as first-class memory** (#70) — Sigma and YARA rules
17
+ are now ingested, indexed, and retrieved alongside CTI entities, with
18
+ an LLM rule explainer that surfaces what each rule detects and the
19
+ actors/techniques it's associated with. See the "Detection Rules as
20
+ Memory" section in the README (#74) for usage.
21
+ - **MCP Registry publication** (#75) — `server.json` and the `mcp-name`
22
+ tag required to publish ZettelForge to the canonical MCP Registry
23
+ (registry.modelcontextprotocol.io), which feeds mcp.so and the
24
+ modelcontextprotocol.io community-servers list.
25
+ - **Brand & docs polish** (#61) — neural-chain architecture diagram with
26
+ light/dark parity, updated GitHub social preview, canonical security
27
+ channels + RFC 9116 `security.txt`, real Code of Conduct contacts,
28
+ and a complete brand documentation set.
29
+
30
+ ### Fixed
31
+
32
+ - **SQLite backend concurrency** (#69) — 16 reader methods in
33
+ `SQLiteBackend` (`get_note_by_id`, `get_note_by_source_ref`,
34
+ `iterate_notes`, `get_notes_by_domain`, `get_recent_notes`,
35
+ `count_notes`, `get_kg_node`, `get_kg_node_by_id`,
36
+ `get_kg_neighbors`, `traverse_kg`, `get_entity_timeline`,
37
+ `get_changes_since`, `get_causal_edges`, `get_incoming_causal`,
38
+ `get_note_ids_for_entity`, `search_entities`) were executing
39
+ `SELECT` statements without holding `_write_lock`, while writers
40
+ acquired it. Under concurrent background enrichment, readers could
41
+ observe a partially-written row and raise `pydantic.ValidationError`
42
+ on NULL columns. Each reader now wraps its SQL execute+fetch block
43
+ in `with self._write_lock:` (RLock, reentrant-safe). Closes #68.
44
+ Eliminates the `test_apply_delete_marks_superseded` flake and
45
+ prevents the same race from surfacing in production
46
+ `recall()`-during-write paths.
47
+ - **CI regressions** (#67) — stabilized three tests exposed by the
48
+ test-suite audit sprint.
49
+
50
+ ### Changed
51
+
52
+ - **Test suite hygiene** (#62, #63, #64, #65) — post-v2.3.0 audit (see
53
+ `docs/superpowers/research/2026-04-17-test-suite-audit.md`)
54
+ converted 10 CI-skipped LLM tests to the mock provider (RFC-002
55
+ Phase 1), resolved both remaining `xfail` tests via prompt-routed
56
+ mocks, eliminated two long-standing flakes
57
+ (`test_recall_cve_returns_notes`, `test_apply_delete_marks_superseded`),
58
+ prepped `langchain_retriever` for Pydantic V3 by migrating to
59
+ `ConfigDict`, and reinstated meaningful causal-edge validation via
60
+ mock-seeded triples + `SQLiteBackend.get_causal_edges` query. Net
61
+ test-suite delta: 280 passed / 17 skipped / 2 xfailed → 305 passed
62
+ / 10 skipped / 0 xfailed on test-3.12.
63
+
64
+ ## [2.3.0] - 2026-04-17
65
+
66
+ Pluggable LLM provider infrastructure (RFC-002 Phase 1), MCP server
67
+ as a first-class Python module, PyPI discoverability refresh, SEO
68
+ foundations across the docs site, and a full docs-vs-code
69
+ reconciliation. All additions are backward-compatible; no existing
70
+ API changes. Supersedes the never-tagged 2.2.1 metadata patch —
71
+ its PyPI classifier / keyword / image-URL changes are folded in
72
+ below.
73
+
74
+ ### Added
75
+
76
+ - **Pluggable LLM provider infrastructure (RFC-002 Phase 1)** — new
77
+ `zettelforge.llm_providers` package with a `@runtime_checkable`
78
+ `LLMProvider` protocol, a thread-safe registry, and built-in
79
+ providers for `local` (llama-cpp-python), `ollama`, and `mock`.
80
+ The public `generate()` signature is unchanged; all 7 existing call
81
+ sites (`fact_extractor`, `memory_updater`, `synthesis_generator`,
82
+ `intent_classifier`, `note_constructor`, `entity_indexer`,
83
+ `memory_evolver`) keep working without modification. Third-party
84
+ providers can register via the `zettelforge.llm_providers`
85
+ entry-point group. `openai_compat` and `anthropic` providers land
86
+ in Phase 2 and Phase 3.
87
+ - **`LLMConfig` expanded** — new `api_key`, `timeout`, `max_retries`,
88
+ `fallback`, and `extra` fields. `api_key` supports `${ENV_VAR}`
89
+ references and is redacted from `repr()`. Sensitive keys inside
90
+ `extra` (matching `key|token|secret|password|credential|auth`) are
91
+ redacted as well. New env overrides: `ZETTELFORGE_LLM_API_KEY`,
92
+ `ZETTELFORGE_LLM_TIMEOUT`, `ZETTELFORGE_LLM_MAX_RETRIES`,
93
+ `ZETTELFORGE_LLM_FALLBACK`.
94
+ - **`LLMProviderConfigurationError`** — new exception surfaced for
95
+ non-recoverable provider setup problems (bad API key, missing
96
+ optional SDK) so `generate()` can distinguish "try the fallback"
97
+ from "stop and report".
98
+ - **`llm_client.reload()` helper** — clears the provider registry
99
+ and config cache so test suites and long-lived processes can
100
+ reconfigure the LLM backend without a process restart.
101
+ - **Hardened .gitignore** per GOV-023 — added `.env.*`, `*.key`,
102
+ `*.pem`.
103
+ - **MCP server as a first-class module** — `python -m zettelforge.mcp`
104
+ now works out of a `pip install zettelforge` with no git clone
105
+ required. New package `zettelforge.mcp` (with `server.py`,
106
+ `__main__.py`, and a console-script entry `zettelforge-mcp`).
107
+ The previous entry point at `web/mcp_server.py` is retained as a
108
+ thin backward-compat shim.
109
+ - **Console scripts** — `zettelforge` and `zettelforge-mcp` entry
110
+ points added to `pyproject.toml`.
111
+ - **How-to guides** — migration (`migrate-jsonl-to-sqlite.md`),
112
+ benchmark reproduction (`reproduce-benchmarks.md`), troubleshooting
113
+ (`troubleshoot.md`), and upgrade (`upgrade.md`). Linked from the
114
+ MkDocs nav.
115
+ - **Design and About sections in the docs nav** — RFC-001, RFC-002,
116
+ RFC-003 and the origin-story narrative are now discoverable from
117
+ `docs.threatrecall.ai`.
118
+ - **RFC-003 design proposal (docs only)** — read-path depth routing
119
+ with a deterministic Quality Gate plus System 1 / System 2 recall
120
+ paths. Ships with an adversarial-review artifact (4 blockers, 13
121
+ warnings). No runtime changes yet — implementation deferred.
122
+ - **Archive directory** — `docs/archive/` holds retired v1.0.0-alpha
123
+ snapshots (`SKILL.md`, `PACKAGE_SUMMARY.md`) with a README explaining
124
+ their provenance.
125
+ - **`llm_ner` configuration reference** — `docs/reference/configuration.md`
126
+ now documents `llm_ner.enabled` and the `ZETTELFORGE_LLM_NER_ENABLED`
127
+ environment override.
128
+ - **Docs SEO foundation** — per-page canonical URLs, OpenGraph and
129
+ Twitter-card metadata, and a `SoftwareApplication` JSON-LD block on
130
+ the home page via a `docs/overrides/main.html` theme override. The
131
+ `softwareVersion` value is sourced from `config.extra.version` in
132
+ `mkdocs.yml` so it stays in sync with releases.
133
+ - **PyPI classifier refresh** — added `Topic :: Security` (primary
134
+ filter security engineers use to browse PyPI) and
135
+ `Topic :: Software Development :: Libraries :: Python Modules`.
136
+ Existing `Topic :: Scientific/Engineering :: Artificial Intelligence`
137
+ retained. Development Status stays at `4 - Beta`.
138
+ - **PyPI keyword refresh** — swapped `agent-memory` → `agentic-memory`
139
+ (emerging category keyword) and `zettelkasten` → `llm-memory`
140
+ (direct intent match for Mem0/Graphiti discovery traffic). Still
141
+ 10 keywords total; within the PyPI display limit.
142
+
143
+ ### Changed
144
+
145
+ - **SECURITY.md** — contact updated to `contact@threatrecall.ai`,
146
+ supported-versions table refreshed to mark `2.3.x` as current and
147
+ `2.2.x` as the prior minor release; storage section refreshed to
148
+ reflect SQLite-by-default.
149
+ - **`docs/llms.txt`** — rewritten to match current reality (SQLite
150
+ default, 19 runtime entity types, correct GOV-003/007/011/012
151
+ descriptions, MCP invocation).
152
+ - **BENCHMARK_REPORT.md** — CTIBench ATE row updated (F1 = 0.146);
153
+ architecture summary reframed as SQLite + LanceDB default with
154
+ TypeDB as an extension; `ctibench_results.json` date bumped.
155
+ - **README** — above-fold rewritten (CTA row, keyword density,
156
+ PyPI-safe absolute-URL images). Pipeline step 1 entity count
157
+ corrected from "10 types" to the 19 types `EntityExtractor`
158
+ actually recognises.
159
+ - **README image paths** — `docs/assets/demo.gif` and
160
+ `docs/assets/zettelforge_architecture.svg` rewritten to absolute
161
+ `raw.githubusercontent.com` URLs so the PyPI long description
162
+ renders correctly (relative paths 404 on the PyPI CDN). Pinned to
163
+ the `master` ref; can be re-pinned to the `v2.3.0` tag in the
164
+ next release PR if PyPI-side stability matters.
165
+ - **`docs/superpowers/plans/` renamed to `docs/superpowers/research/`**
166
+ with a README making clear these are aspirational synthesis, not
167
+ roadmap commitments. The stray untracked `docs/plans/` directory
168
+ was removed.
169
+ - **Tutorials and governance-controls reference** — `last_updated`
170
+ and `version` metadata refreshed.
171
+ - **`zettelforge.ontology` exports** — `TypedEntityStore`,
172
+ `OntologyValidator`, `get_ontology_store`, `get_ontology_validator`
173
+ removed from the top-level `__all__` (still importable from
174
+ `zettelforge.ontology`). They are a parallel store not wired into
175
+ `MemoryManager`.
176
+ - **`observability.py` and `cache.py` headers** — annotated as
177
+ currently unwired; kept for future integration.
178
+ - **OCSF `_PRODUCT_VERSION`** — sourced from
179
+ `importlib.metadata.version("zettelforge")` instead of a hard-coded
180
+ string, so emitted OCSF events stop drifting when `__version__`
181
+ bumps.
182
+ - **OpenGraph `og:type`** — `website` on the home page, `article`
183
+ elsewhere (was unconditionally `article`).
184
+
185
+ ### Fixed
186
+
187
+ - **OllamaProvider host routing** — now instantiates
188
+ `ollama.Client(host=self._url)` so the configured URL actually
189
+ takes effect (previously the module-level `ollama.generate()` call
190
+ ignored per-instance host).
191
+ - **Provider registry race** — `register()` now checks and mutates
192
+ under the registry lock, closing a TOCTOU window on concurrent
193
+ provider registration.
194
+ - **MCP server lazy instantiation** — `MemoryManager` is now created
195
+ on first tool call rather than at server import time, so `--help`
196
+ and protocol-handshake tests don't pay the model-load cost.
197
+
198
+ ### Removed
199
+
200
+ - Six superseded branches that had already been squash-merged into
201
+ master — `feat/causal-chain-fix-and-demo-gif`,
202
+ `feat/entity-vocabulary-expansion`,
203
+ `feature/RFC-001-conversational-entity-extractor`,
204
+ `fix/intent-classifier-graph-weight`,
205
+ `fix/p0-production-blockers`, `feat/remember-evolve`.
206
+
9
207
  ## [2.2.0] - 2026-04-16
10
208
 
11
209
  SQLite default backend, causal chain retrieval, memory evolution, STIX taxonomy alignment, and community-first package cleanup.
@@ -37,7 +37,7 @@ This Code of Conduct applies within all community spaces, and also applies when
37
37
 
38
38
  ## Enforcement
39
39
 
40
- Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly.
40
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement by email at **conduct@threatrecall.ai**, or privately via GitHub's [report abuse](https://github.com/rolandpg/zettelforge/security/advisories/new) flow. All complaints will be reviewed and investigated promptly and fairly.
41
41
 
42
42
  All community leaders are obligated to respect the privacy and security of the reporter of any incident.
43
43
 
@@ -1,30 +1,37 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zettelforge
3
- Version: 2.2.0
3
+ Version: 2.4.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
28
+ Requires-Dist: jsonschema>=4.0
24
29
  Requires-Dist: lancedb>=0.5.0
25
30
  Requires-Dist: numpy>=1.24.0
31
+ Requires-Dist: plyara>=2.0
26
32
  Requires-Dist: pyarrow>=14.0.0
27
33
  Requires-Dist: pydantic>=2.0.0
34
+ Requires-Dist: pyyaml>=6.0
28
35
  Requires-Dist: requests>=2.31.0
29
36
  Requires-Dist: structlog>=24.0.0
30
37
  Requires-Dist: tantivy>=0.11.0
@@ -48,23 +55,28 @@ Description-Content-Type: text/markdown
48
55
 
49
56
  # ZettelForge
50
57
 
58
+ <!-- mcp-name: io.github.rolandpg/zettelforge -->
59
+
51
60
  **The only agentic memory system built for cyber threat intelligence.**
52
61
 
53
- Give your AI agents persistent memory with entity extraction, knowledge graphs, and STIX ontology -- no cloud, no API keys, works offline.
62
+ 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
63
 
55
64
  [![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)
65
+ [![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
66
  [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)
67
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://opensource.org/licenses/MIT)
60
68
  [![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)
69
+
70
+ **[ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted](https://threatrecall.ai)**
64
71
 
65
72
  <p align="center">
66
- <img src="docs/assets/demo.gif" width="720" alt="ZettelForge demo CTI agentic memory in action">
73
+ <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>
67
74
  </p>
75
+ <p align="center">
76
+ <img src="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/demo.gif" width="720" alt="ZettelForge demo — CTI agentic memory in action">
77
+ </p>
78
+
79
+ > If ZettelForge fits a CTI workflow you run, a star is the fastest signal that this category is worth continuing to invest in.
68
80
 
69
81
  ## Why ZettelForge?
70
82
 
@@ -72,6 +84,9 @@ General-purpose memory systems don't understand threat intelligence. They can't
72
84
 
73
85
  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
86
 
87
+ >"Memory augmentation closes 33% of the gap between small and large models on CTI tasks (CTI-REALM, Microsoft 2026)." [1]
88
+
89
+
75
90
  | Feature | ZettelForge | Mem0 | Graphiti | Cognee |
76
91
  |---------|------------|------|----------|--------|
77
92
  | CTI entity extraction (CVEs, actors, IOCs) | Yes | No | No | No |
@@ -83,6 +98,16 @@ ZettelForge was built from the ground up for analysts who think in threat graphs
83
98
  | OCSF audit logging | Yes | No | No | No |
84
99
  | MCP server (Claude Code) | Yes | No | No | No |
85
100
 
101
+ ## Data Pipeline
102
+ <p align="center">
103
+ <picture>
104
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture.svg">
105
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture-light.svg">
106
+ <img src="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture.svg" width="720" alt="ZettelForge architecture — neural recall loop: ingest, enrich, retrieve, synthesize, backed by SQLite + LanceDB">
107
+ </picture>
108
+ </p>
109
+
110
+
86
111
  ## Features
87
112
 
88
113
  **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 +173,7 @@ mm.remember(
148
173
 
149
174
  Every `remember()` call triggers a pipeline:
150
175
 
151
- 1. **Entity Extraction** -- regex + LLM NER identifies CVEs, actors, tools, campaigns, people, locations, orgs (10 types)
176
+ 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
177
  2. **Knowledge Graph Update** -- entities become nodes, co-occurrence becomes edges, LLM infers causal triples
153
178
  3. **Vector Embedding** -- 768-dim fastembed (ONNX, in-process, 7ms/embed) stored in LanceDB
154
179
  4. **Supersession Check** -- entity overlap detection marks stale notes as superseded
@@ -192,6 +217,35 @@ Your Claude Code agent can now remember and recall threat intelligence across se
192
217
 
193
218
  Exposed tools: `remember`, `recall`, `synthesize`, `entity`, `graph`, `stats`.
194
219
 
220
+ ## Detection Rules as Memory (Sigma + YARA)
221
+
222
+ Sigma and YARA rules are first-class memory primitives. Parse, validate, and ingest a rule and its tags become graph edges: MITRE ATT&CK techniques, CVEs, threat-actor aliases, tools, and malware families resolve against the same ontology as every other note. A shared `DetectionRule` supertype carries `SigmaRule` and `YaraRule` subtypes, so a single rule UUID is addressable across both formats.
223
+
224
+ Sigma rules are validated against the vendored [SigmaHQ JSON schema](https://github.com/SigmaHQ/sigma-specification). YARA rules are parsed with plyara and validated against the [CCCS YARA metadata standard](https://github.com/CybercentreCanada/CCCS-Yara) (tiers: `strict`, `warn`, `non_cccs`). Ingest is idempotent -- re-ingesting an unchanged rule returns the original note via a content-hashed `source_ref`.
225
+
226
+ ```python
227
+ from zettelforge import MemoryManager
228
+ from zettelforge.sigma import ingest_rule as ingest_sigma
229
+ from zettelforge.yara import ingest_rule as ingest_yara
230
+
231
+ mm = MemoryManager()
232
+ ingest_sigma("rules/proc_creation_win_office_macro.yml", mm)
233
+ ingest_yara("rules/webshell_china_chopper.yar", mm, tier="warn")
234
+ ```
235
+
236
+ ```bash
237
+ # Bulk ingest from SigmaHQ or a private rule repo
238
+ python -m zettelforge.sigma.ingest /path/to/sigma/rules/
239
+ python -m zettelforge.yara.ingest /path/to/yara/rules/ --tier warn
240
+
241
+ # CI fixture check -- parse + validate, no writes
242
+ python -m zettelforge.sigma.ingest rules/ --dry-run
243
+ ```
244
+
245
+ An LLM rule explainer (`zettelforge.detection.explainer.explain`) produces a structured JSON summary -- intent, key fields, evasion notes, false-positive hypotheses -- for any `DetectionRule`. It runs synchronously on demand in v1; async enrichment-queue wiring is v1.1. Rate-limited via `ZETTELFORGE_EXPLAIN_RPM` (default 60 calls/minute).
246
+
247
+ References: [Sigma spec](https://github.com/SigmaHQ/sigma-specification), [SigmaHQ rules](https://github.com/SigmaHQ/sigma), [CCCS YARA](https://github.com/CybercentreCanada/CCCS-Yara), [YARA docs](https://yara.readthedocs.io).
248
+
195
249
  ## Integrations
196
250
 
197
251
  ### ATHF (Agentic Threat Hunting Framework)
@@ -206,26 +260,6 @@ python examples/athf_bridge.py /path/to/hunts/
206
260
 
207
261
  See [examples/athf_bridge.py](examples/athf_bridge.py).
208
262
 
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
263
 
230
264
  ## Extensions
231
265
 
@@ -272,6 +306,12 @@ MIT -- See [LICENSE](LICENSE).
272
306
 
273
307
  **Made by Patrick Roland**.
274
308
 
309
+ ## Support the Project
310
+
311
+ ZettelForge is MIT-licensed. If it's useful in your workflow and you'd like to help keep it maintained:
312
+
313
+ <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>
314
+
275
315
  ## Acknowledgments
276
316
 
277
317
  - Inspired by [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) and [A-Mem](https://arxiv.org/abs/2602.10715) (NeurIPS 2025)
@@ -279,3 +319,5 @@ MIT -- See [LICENSE](LICENSE).
279
319
  - STIX 2.1 schema informed by [typedb-cti](https://github.com/typedb-osi/typedb-cti)
280
320
  - Benchmarked against [LOCOMO](https://snap-research.github.io/locomo/) (ACL 2024) and [CTIBench](https://arxiv.org/abs/2406.07599) (NeurIPS 2024)
281
321
  - [LanceDB](https://lancedb.com) | [fastembed](https://github.com/qdrant/fastembed) | [Pydantic](https://pydantic.dev) | [TypeDB](https://typedb.com)
322
+
323
+ [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/