zettelforge 2.3.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 (286) hide show
  1. {zettelforge-2.3.0 → zettelforge-2.4.0}/CHANGELOG.md +55 -0
  2. {zettelforge-2.3.0 → zettelforge-2.4.0}/CODE_OF_CONDUCT.md +1 -1
  3. {zettelforge-2.3.0 → zettelforge-2.4.0}/PKG-INFO +40 -2
  4. {zettelforge-2.3.0 → zettelforge-2.4.0}/README.md +36 -1
  5. {zettelforge-2.3.0 → zettelforge-2.4.0}/SECURITY.md +24 -3
  6. zettelforge-2.4.0/docs/.well-known/security.txt +10 -0
  7. zettelforge-2.4.0/docs/assets/favicon-16.png +0 -0
  8. zettelforge-2.4.0/docs/assets/favicon-32.png +0 -0
  9. zettelforge-2.4.0/docs/assets/favicon-512.png +0 -0
  10. zettelforge-2.4.0/docs/assets/favicon-64.png +0 -0
  11. zettelforge-2.4.0/docs/assets/favicon-apple-touch.png +0 -0
  12. zettelforge-2.4.0/docs/assets/favicon.svg +33 -0
  13. zettelforge-2.4.0/docs/assets/logo.svg +46 -0
  14. zettelforge-2.4.0/docs/assets/social-preview.png +0 -0
  15. zettelforge-2.4.0/docs/assets/threatrecall-lockup-monogram.svg +41 -0
  16. zettelforge-2.4.0/docs/assets/threatrecall-lockup.svg +39 -0
  17. zettelforge-2.4.0/docs/assets/threatrecall-logo-flat.svg +29 -0
  18. zettelforge-2.4.0/docs/assets/zettelforge_architecture-light.svg +105 -0
  19. zettelforge-2.4.0/docs/assets/zettelforge_architecture.svg +105 -0
  20. zettelforge-2.4.0/docs/brand/brandIdentity.md +266 -0
  21. zettelforge-2.4.0/docs/brand/colors_and_type.css +286 -0
  22. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/migrate-jsonl-to-sqlite.md +3 -1
  23. zettelforge-2.4.0/docs/stylesheets/brand-tokens.css +158 -0
  24. zettelforge-2.4.0/docs/stylesheets/extra.css +70 -0
  25. zettelforge-2.4.0/docs/stylesheets/fonts/Neuropol.otf +0 -0
  26. zettelforge-2.4.0/docs/superpowers/research/2026-04-17-test-suite-audit.md +178 -0
  27. {zettelforge-2.3.0 → zettelforge-2.4.0}/mkdocs.yml +10 -1
  28. {zettelforge-2.3.0 → zettelforge-2.4.0}/pyproject.toml +5 -1
  29. zettelforge-2.4.0/server.json +21 -0
  30. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/__init__.py +1 -1
  31. zettelforge-2.4.0/src/zettelforge/detection/__init__.py +24 -0
  32. zettelforge-2.4.0/src/zettelforge/detection/base.py +63 -0
  33. zettelforge-2.4.0/src/zettelforge/detection/consumers.py +77 -0
  34. zettelforge-2.4.0/src/zettelforge/detection/explainer.py +320 -0
  35. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/integrations/langchain_retriever.py +3 -6
  36. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/ontology.py +129 -4
  37. zettelforge-2.4.0/src/zettelforge/sigma/__init__.py +31 -0
  38. zettelforge-2.4.0/src/zettelforge/sigma/cli.py +123 -0
  39. zettelforge-2.4.0/src/zettelforge/sigma/entities.py +249 -0
  40. zettelforge-2.4.0/src/zettelforge/sigma/ingest.py +234 -0
  41. zettelforge-2.4.0/src/zettelforge/sigma/parser.py +148 -0
  42. zettelforge-2.4.0/src/zettelforge/sigma/schemas/NOTICE.md +10 -0
  43. zettelforge-2.4.0/src/zettelforge/sigma/schemas/__init__.py +1 -0
  44. zettelforge-2.4.0/src/zettelforge/sigma/schemas/sigma-correlation-rules-schema.json +326 -0
  45. zettelforge-2.4.0/src/zettelforge/sigma/schemas/sigma-detection-rule-schema.json +247 -0
  46. zettelforge-2.4.0/src/zettelforge/sigma/schemas/sigma-filters-schema.json +101 -0
  47. zettelforge-2.4.0/src/zettelforge/sigma/tags.py +86 -0
  48. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/sqlite_backend.py +156 -124
  49. zettelforge-2.4.0/src/zettelforge/yara/__init__.py +27 -0
  50. zettelforge-2.4.0/src/zettelforge/yara/cccs_metadata.py +258 -0
  51. zettelforge-2.4.0/src/zettelforge/yara/cli.py +177 -0
  52. zettelforge-2.4.0/src/zettelforge/yara/entities.py +269 -0
  53. zettelforge-2.4.0/src/zettelforge/yara/ingest.py +327 -0
  54. zettelforge-2.4.0/src/zettelforge/yara/parser.py +110 -0
  55. zettelforge-2.4.0/src/zettelforge/yara/schemas/CCCS_YARA.yml +306 -0
  56. zettelforge-2.4.0/src/zettelforge/yara/schemas/CCCS_YARA_values.yml +160 -0
  57. zettelforge-2.4.0/src/zettelforge/yara/schemas/NOTICE.md +11 -0
  58. zettelforge-2.4.0/src/zettelforge/yara/schemas/__init__.py +1 -0
  59. zettelforge-2.4.0/src/zettelforge/yara/tags.py +74 -0
  60. zettelforge-2.4.0/tests/fixtures/sigma/cloud_example.yml +20 -0
  61. zettelforge-2.4.0/tests/fixtures/sigma/correlation_example.yml +14 -0
  62. zettelforge-2.4.0/tests/fixtures/sigma/process_creation_example.yml +17 -0
  63. zettelforge-2.4.0/tests/fixtures/sigma/tagged_example.yml +30 -0
  64. zettelforge-2.4.0/tests/fixtures/yara/malware_hash.yar +19 -0
  65. zettelforge-2.4.0/tests/fixtures/yara/technique_loader.yar +23 -0
  66. zettelforge-2.4.0/tests/fixtures/yara/webshell.yar +19 -0
  67. zettelforge-2.4.0/tests/test_causal_extraction.py +102 -0
  68. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_conversational_entities.py +50 -11
  69. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_core.py +2 -2
  70. zettelforge-2.4.0/tests/test_detection_explainer.py +328 -0
  71. zettelforge-2.4.0/tests/test_detection_rule_entities.py +104 -0
  72. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_langchain_retriever.py +5 -1
  73. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_llm_client.py +63 -1
  74. zettelforge-2.4.0/tests/test_sigma_entities.py +205 -0
  75. zettelforge-2.4.0/tests/test_sigma_ingest.py +212 -0
  76. zettelforge-2.4.0/tests/test_sigma_parser.py +125 -0
  77. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_two_phase_e2e.py +18 -15
  78. zettelforge-2.4.0/tests/test_yara_entities.py +170 -0
  79. zettelforge-2.4.0/tests/test_yara_ingest.py +126 -0
  80. zettelforge-2.4.0/tests/test_yara_parser.py +126 -0
  81. zettelforge-2.3.0/docs/assets/logo.svg +0 -3
  82. zettelforge-2.3.0/docs/assets/social-preview.png +0 -0
  83. zettelforge-2.3.0/docs/assets/threatrecall-logo.svg +0 -22
  84. zettelforge-2.3.0/docs/assets/threatrecall-mark.svg +0 -12
  85. zettelforge-2.3.0/docs/assets/zettelforge_architecture.svg +0 -77
  86. zettelforge-2.3.0/docs/stylesheets/extra.css +0 -10
  87. zettelforge-2.3.0/tests/test_causal_extraction.py +0 -91
  88. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/CODEOWNERS +0 -0
  89. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  90. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  91. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/SECURITY.md +0 -0
  92. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/dependabot.yml +0 -0
  93. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/pull_request_template.md +0 -0
  94. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/workflows/ci.yml +0 -0
  95. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/workflows/docs.yml +0 -0
  96. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/workflows/publish.yml +0 -0
  97. {zettelforge-2.3.0 → zettelforge-2.4.0}/.github/workflows/snyk-security.yml +0 -0
  98. {zettelforge-2.3.0 → zettelforge-2.4.0}/.gitignore +0 -0
  99. {zettelforge-2.3.0 → zettelforge-2.4.0}/ARCHITECTURE.md +0 -0
  100. {zettelforge-2.3.0 → zettelforge-2.4.0}/CODEOWNERS +0 -0
  101. {zettelforge-2.3.0 → zettelforge-2.4.0}/CONTRIBUTING.md +0 -0
  102. {zettelforge-2.3.0 → zettelforge-2.4.0}/Dockerfile +0 -0
  103. {zettelforge-2.3.0 → zettelforge-2.4.0}/GOVERNANCE.md +0 -0
  104. {zettelforge-2.3.0 → zettelforge-2.4.0}/LICENSE +0 -0
  105. {zettelforge-2.3.0 → zettelforge-2.4.0}/MANIFEST.in +0 -0
  106. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/BENCHMARK_REPORT.md +0 -0
  107. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/LOCOMO_BENCHMARK_COMPARISON.md +0 -0
  108. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/auto_ralph.py +0 -0
  109. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/benchmark_harness.py +0 -0
  110. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/cti_benchmark_v2.py +0 -0
  111. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/cti_retrieval_benchmark.py +0 -0
  112. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/cti_retrieval_results.json +0 -0
  113. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/cti_v2_results.json +0 -0
  114. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/ctibench_benchmark.py +0 -0
  115. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/ctibench_results.json +0 -0
  116. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/dataset.json +0 -0
  117. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/enterprise-attack.json +0 -0
  118. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/evolve_benchmark.py +0 -0
  119. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/evolve_results.json +0 -0
  120. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/graph_test.py +0 -0
  121. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/locomo_benchmark.py +0 -0
  122. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/locomo_results.json +0 -0
  123. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/locomo_results_v1.3.0_baseline.json +0 -0
  124. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/memoryagentbench.py +0 -0
  125. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/memoryagentbench_results.json +0 -0
  126. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/mempalace_benchmark.py +0 -0
  127. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/mempalace_results.json +0 -0
  128. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/naive_memory.py +0 -0
  129. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/opencti_benchmark.py +0 -0
  130. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/ragas_benchmark.py +0 -0
  131. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/ragas_cti_results.json +0 -0
  132. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/ragas_results.json +0 -0
  133. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/results/benchmark_report.md +0 -0
  134. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/results/ralph_optimization_log.json +0 -0
  135. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/scale_benchmark.py +0 -0
  136. {zettelforge-2.3.0 → zettelforge-2.4.0}/benchmarks/scale_results.json +0 -0
  137. {zettelforge-2.3.0 → zettelforge-2.4.0}/config.default.yaml +0 -0
  138. {zettelforge-2.3.0 → zettelforge-2.4.0}/config.example.yaml +0 -0
  139. {zettelforge-2.3.0 → zettelforge-2.4.0}/docker/docker-compose.yml +0 -0
  140. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/CNAME +0 -0
  141. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/architecture-diagram.mmd +0 -0
  142. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/archive/PACKAGE_SUMMARY.md +0 -0
  143. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/archive/README.md +0 -0
  144. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/archive/SKILL.md +0 -0
  145. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/ZettelForge_Architecture.mmd +0 -0
  146. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/architecture-overview.mmd +0 -0
  147. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/architecture-read-path.mmd +0 -0
  148. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/architecture-write-path.mmd +0 -0
  149. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/demo.gif +0 -0
  150. /zettelforge-2.3.0/docs/assets/favicon.svg → /zettelforge-2.4.0/docs/assets/favicon-old.svg +0 -0
  151. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/threatrecall-logo-philosophy.md +0 -0
  152. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/threatrecall-logo.png +0 -0
  153. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/assets/threatrecall-mark.png +0 -0
  154. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/explanation/architecture.md +0 -0
  155. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/explanation/epistemic-tiers.md +0 -0
  156. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/explanation/stix-in-zettelforge.md +0 -0
  157. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/explanation/two-phase-pipeline.md +0 -0
  158. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/explanation/zettelkasten-philosophy.md +0 -0
  159. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/configure-lancedb.md +0 -0
  160. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/configure-opencti.md +0 -0
  161. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/configure-typedb.md +0 -0
  162. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/ingest-news-report.md +0 -0
  163. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/integrate-llm-agent.md +0 -0
  164. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/query-apt-tools.md +0 -0
  165. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/reproduce-benchmarks.md +0 -0
  166. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/resolve-aliases.md +0 -0
  167. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/run-temporal-query.md +0 -0
  168. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/store-threat-actor.md +0 -0
  169. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/troubleshoot.md +0 -0
  170. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/how-to/upgrade.md +0 -0
  171. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/index.md +0 -0
  172. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/llms.txt +0 -0
  173. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/narrative/2026-04-16-the-memory-problem.md +0 -0
  174. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/overrides/main.html +0 -0
  175. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/reference/configuration.md +0 -0
  176. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/reference/governance-controls.md +0 -0
  177. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/reference/memory-manager-api.md +0 -0
  178. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/reference/retrieval-policies.md +0 -0
  179. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/reference/stix-schema.md +0 -0
  180. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/rfcs/RFC-001-conversational-entity-extractor.md +0 -0
  181. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/rfcs/RFC-002-universal-llm-provider.md +0 -0
  182. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/rfcs/RFC-003-adversarial-review.md +0 -0
  183. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/rfcs/RFC-003-read-path-depth-routing.md +0 -0
  184. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-09-ctibench-ragas-benchmarks.md +0 -0
  185. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-09-fastembed-local-embeddings.md +0 -0
  186. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-09-hybrid-typedb-lancedb-architecture.md +0 -0
  187. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-09-local-llm-llama-cpp.md +0 -0
  188. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-anti-aversion-cleanup.md +0 -0
  189. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-causal-graph.md +0 -0
  190. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-ctibench-ate-fix.md +0 -0
  191. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-format-stability.md +0 -0
  192. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-memory-evolution.md +0 -0
  193. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-merge-consolidation.md +0 -0
  194. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-persistence-semantics.md +0 -0
  195. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/2026-04-15-sqlite-migration.md +0 -0
  196. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/research/README.md +0 -0
  197. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/superpowers/specs/2026-04-15-p1-features-prd.md +0 -0
  198. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/tutorials/01-quickstart.md +0 -0
  199. {zettelforge-2.3.0 → zettelforge-2.4.0}/docs/tutorials/02-first-cti-report.md +0 -0
  200. {zettelforge-2.3.0 → zettelforge-2.4.0}/examples/athf_bridge.py +0 -0
  201. {zettelforge-2.3.0 → zettelforge-2.4.0}/examples/mcp_claude_code.md +0 -0
  202. {zettelforge-2.3.0 → zettelforge-2.4.0}/examples/quickstart.py +0 -0
  203. {zettelforge-2.3.0 → zettelforge-2.4.0}/governance/controls.yaml +0 -0
  204. {zettelforge-2.3.0 → zettelforge-2.4.0}/scripts/migrate_jsonl_to_sqlite.py +0 -0
  205. {zettelforge-2.3.0 → zettelforge-2.4.0}/scripts/rebuild_index.py +0 -0
  206. {zettelforge-2.3.0 → zettelforge-2.4.0}/scripts/record-demo.sh +0 -0
  207. {zettelforge-2.3.0 → zettelforge-2.4.0}/scripts/typedb-setup.sh +0 -0
  208. {zettelforge-2.3.0 → zettelforge-2.4.0}/scripts/zettelforge-rebuild.service +0 -0
  209. {zettelforge-2.3.0 → zettelforge-2.4.0}/scripts/zettelforge-rebuild.timer +0 -0
  210. {zettelforge-2.3.0 → zettelforge-2.4.0}/skills/claude-code-skill.md +0 -0
  211. {zettelforge-2.3.0 → zettelforge-2.4.0}/skills/openclaw-skill.md +0 -0
  212. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/__main__.py +0 -0
  213. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/alias_resolver.py +0 -0
  214. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/backend_factory.py +0 -0
  215. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/blended_retriever.py +0 -0
  216. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/cache.py +0 -0
  217. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/config.py +0 -0
  218. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/consolidation.py +0 -0
  219. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/demo.py +0 -0
  220. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/edition.py +0 -0
  221. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/entity_indexer.py +0 -0
  222. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/extensions.py +0 -0
  223. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/fact_extractor.py +0 -0
  224. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/governance_validator.py +0 -0
  225. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/graph_retriever.py +0 -0
  226. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/integrations/__init__.py +0 -0
  227. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/intent_classifier.py +0 -0
  228. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/json_parse.py +0 -0
  229. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/knowledge_graph.py +0 -0
  230. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_client.py +0 -0
  231. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_providers/__init__.py +0 -0
  232. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_providers/base.py +0 -0
  233. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_providers/local_provider.py +0 -0
  234. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_providers/mock_provider.py +0 -0
  235. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_providers/ollama_provider.py +0 -0
  236. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/llm_providers/registry.py +0 -0
  237. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/log.py +0 -0
  238. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/mcp/__init__.py +0 -0
  239. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/mcp/__main__.py +0 -0
  240. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/mcp/server.py +0 -0
  241. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/memory_evolver.py +0 -0
  242. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/memory_manager.py +0 -0
  243. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/memory_store.py +0 -0
  244. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/memory_updater.py +0 -0
  245. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/note_constructor.py +0 -0
  246. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/note_schema.py +0 -0
  247. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/observability.py +0 -0
  248. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/ocsf.py +0 -0
  249. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/retry.py +0 -0
  250. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/storage_backend.py +0 -0
  251. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/synthesis_generator.py +0 -0
  252. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/synthesis_validator.py +0 -0
  253. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/vector_memory.py +0 -0
  254. {zettelforge-2.3.0 → zettelforge-2.4.0}/src/zettelforge/vector_retriever.py +0 -0
  255. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/__init__.py +0 -0
  256. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/benchmark_scale.py +0 -0
  257. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/conftest.py +0 -0
  258. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_basic.py +0 -0
  259. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_blended_retriever.py +0 -0
  260. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_config.py +0 -0
  261. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_consolidation.py +0 -0
  262. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_cti_integration.py +0 -0
  263. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_edition.py +0 -0
  264. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_embedding.py +0 -0
  265. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_extensions.py +0 -0
  266. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_fact_extractor.py +0 -0
  267. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_governance.py +0 -0
  268. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_governance_spec_drift.py +0 -0
  269. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_graph_retriever.py +0 -0
  270. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_intent_classifier.py +0 -0
  271. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_json_parse.py +0 -0
  272. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_llm_providers.py +0 -0
  273. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_logging_compliance.py +0 -0
  274. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_mcp_server.py +0 -0
  275. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_memory_evolver.py +0 -0
  276. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_memory_updater.py +0 -0
  277. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_performance.py +0 -0
  278. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_recall_integration.py +0 -0
  279. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_sqlite_backend.py +0 -0
  280. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_sqlite_integration.py +0 -0
  281. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_storage_backend.py +0 -0
  282. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_temporal_graph.py +0 -0
  283. {zettelforge-2.3.0 → zettelforge-2.4.0}/tests/test_typedb_client.py +0 -0
  284. {zettelforge-2.3.0 → zettelforge-2.4.0}/web/app.py +0 -0
  285. {zettelforge-2.3.0 → zettelforge-2.4.0}/web/auth.py +0 -0
  286. {zettelforge-2.3.0 → zettelforge-2.4.0}/web/mcp_server.py +0 -0
@@ -6,6 +6,61 @@ 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
+
9
64
  ## [2.3.0] - 2026-04-17
10
65
 
11
66
  Pluggable LLM provider infrastructure (RFC-002 Phase 1), MCP server
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zettelforge
3
- Version: 2.3.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
6
  Project-URL: Documentation, https://docs.threatrecall.ai
@@ -25,10 +25,13 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
25
  Requires-Python: >=3.10
26
26
  Requires-Dist: fastembed>=0.8.0
27
27
  Requires-Dist: httpx>=0.25.0
28
+ Requires-Dist: jsonschema>=4.0
28
29
  Requires-Dist: lancedb>=0.5.0
29
30
  Requires-Dist: numpy>=1.24.0
31
+ Requires-Dist: plyara>=2.0
30
32
  Requires-Dist: pyarrow>=14.0.0
31
33
  Requires-Dist: pydantic>=2.0.0
34
+ Requires-Dist: pyyaml>=6.0
32
35
  Requires-Dist: requests>=2.31.0
33
36
  Requires-Dist: structlog>=24.0.0
34
37
  Requires-Dist: tantivy>=0.11.0
@@ -52,6 +55,8 @@ Description-Content-Type: text/markdown
52
55
 
53
56
  # ZettelForge
54
57
 
58
+ <!-- mcp-name: io.github.rolandpg/zettelforge -->
59
+
55
60
  **The only agentic memory system built for cyber threat intelligence.**
56
61
 
57
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.
@@ -95,7 +100,11 @@ ZettelForge was built from the ground up for analysts who think in threat graphs
95
100
 
96
101
  ## Data Pipeline
97
102
  <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">
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>
99
108
  </p>
100
109
 
101
110
 
@@ -208,6 +217,35 @@ Your Claude Code agent can now remember and recall threat intelligence across se
208
217
 
209
218
  Exposed tools: `remember`, `recall`, `synthesize`, `entity`, `graph`, `stats`.
210
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
+
211
249
  ## Integrations
212
250
 
213
251
  ### ATHF (Agentic Threat Hunting Framework)
@@ -1,5 +1,7 @@
1
1
  # ZettelForge
2
2
 
3
+ <!-- mcp-name: io.github.rolandpg/zettelforge -->
4
+
3
5
  **The only agentic memory system built for cyber threat intelligence.**
4
6
 
5
7
  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.
@@ -43,7 +45,11 @@ ZettelForge was built from the ground up for analysts who think in threat graphs
43
45
 
44
46
  ## Data Pipeline
45
47
  <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">
48
+ <picture>
49
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture.svg">
50
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/rolandpg/zettelforge/master/docs/assets/zettelforge_architecture-light.svg">
51
+ <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">
52
+ </picture>
47
53
  </p>
48
54
 
49
55
 
@@ -156,6 +162,35 @@ Your Claude Code agent can now remember and recall threat intelligence across se
156
162
 
157
163
  Exposed tools: `remember`, `recall`, `synthesize`, `entity`, `graph`, `stats`.
158
164
 
165
+ ## Detection Rules as Memory (Sigma + YARA)
166
+
167
+ 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.
168
+
169
+ 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`.
170
+
171
+ ```python
172
+ from zettelforge import MemoryManager
173
+ from zettelforge.sigma import ingest_rule as ingest_sigma
174
+ from zettelforge.yara import ingest_rule as ingest_yara
175
+
176
+ mm = MemoryManager()
177
+ ingest_sigma("rules/proc_creation_win_office_macro.yml", mm)
178
+ ingest_yara("rules/webshell_china_chopper.yar", mm, tier="warn")
179
+ ```
180
+
181
+ ```bash
182
+ # Bulk ingest from SigmaHQ or a private rule repo
183
+ python -m zettelforge.sigma.ingest /path/to/sigma/rules/
184
+ python -m zettelforge.yara.ingest /path/to/yara/rules/ --tier warn
185
+
186
+ # CI fixture check -- parse + validate, no writes
187
+ python -m zettelforge.sigma.ingest rules/ --dry-run
188
+ ```
189
+
190
+ 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).
191
+
192
+ 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).
193
+
159
194
  ## Integrations
160
195
 
161
196
  ### ATHF (Agentic Threat Hunting Framework)
@@ -1,5 +1,26 @@
1
1
  # Security Policy
2
2
 
3
+ ## Canonical Channels
4
+
5
+ To avoid supply-chain and impersonation risk, only the following are
6
+ official distribution channels for ZettelForge and ThreatRecall:
7
+
8
+ | Artifact | Canonical URL |
9
+ |---|---|
10
+ | Source repository | https://github.com/rolandpg/zettelforge |
11
+ | Python package | https://pypi.org/project/zettelforge/ |
12
+ | Release artifacts | https://github.com/rolandpg/zettelforge/releases |
13
+ | Documentation | https://docs.threatrecall.ai/ |
14
+ | Official hosted service | https://threatrecall.ai/ |
15
+ | Security disclosure | contact@threatrecall.ai (this file) |
16
+
17
+ Packages installed from anywhere else — including any `zettelforge-*`
18
+ typosquats, alternate PyPI mirrors, forks published under a different
19
+ namespace, or third-party "ZettelForge Cloud" / "ThreatRecall" hosted
20
+ services — are not affiliated with this project and have not been
21
+ reviewed by the maintainers. Verify provenance via the signed release
22
+ artifacts when in doubt.
23
+
3
24
  ## Reporting a Vulnerability
4
25
 
5
26
  **Do not open a public GitHub issue for security vulnerabilities.**
@@ -39,9 +60,9 @@ backported to the prior minor release.
39
60
 
40
61
  | Version | Supported |
41
62
  |---|---|
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 |
63
+ | 2.4.x (current) | Yes — active security support |
64
+ | 2.3.x | Critical fixes only, for 60 days after 2.4.0 release |
65
+ | < 2.3 | No — upgrade required |
45
66
 
46
67
  ---
47
68
 
@@ -0,0 +1,10 @@
1
+ # ZettelForge / ThreatRecall security.txt
2
+ # RFC 9116 — https://www.rfc-editor.org/rfc/rfc9116
3
+ # Canonical source: https://github.com/rolandpg/zettelforge/blob/master/docs/.well-known/security.txt
4
+
5
+ Contact: mailto:contact@threatrecall.ai
6
+ Contact: https://github.com/rolandpg/zettelforge/security/advisories/new
7
+ Expires: 2027-04-17T00:00:00Z
8
+ Preferred-Languages: en
9
+ Canonical: https://docs.threatrecall.ai/.well-known/security.txt
10
+ Policy: https://github.com/rolandpg/zettelforge/blob/master/SECURITY.md
@@ -0,0 +1,33 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 480">
2
+
3
+ <defs>
4
+ <linearGradient id="fg" x1="0" y1="0" x2="0" y2="1">
5
+ <stop offset="0%" stop-color="#8ED1A0"></stop>
6
+ <stop offset="100%" stop-color="#5EAE78"></stop>
7
+ </linearGradient>
8
+ </defs>
9
+
10
+
11
+ <path d="M55 35 H345 a16 16 0 0 1 16 16 V265 c0 96 -71 162 -161 196&#xA; c-90 -34 -161 -100 -161 -196 V51 a16 16 0 0 1 16 -16 Z" fill="url(#fg)"></path>
12
+
13
+
14
+ <path d="M200 178 C198 215 191 252 192 274 S199 338 200 358" fill="none" stroke="#fff" stroke-width="14" stroke-linecap="round" stroke-dasharray="8 34" opacity="0.45"></path>
15
+
16
+
17
+ <circle cx="200" cy="172" r="38" fill="#fff"></circle>
18
+
19
+
20
+ <path d="M128,96 C128,113 131,116 148,116 C131,116 128,119 128,136&#xA; C128,119 125,116 108,116 C125,116 128,113 128,96 Z" fill="#fff"></path>
21
+ <path d="M272,96 C272,113 275,116 292,116 C275,116 272,119 272,136&#xA; C272,119 269,116 252,116 C269,116 272,113 272,96 Z" fill="#fff"></path>
22
+ <path d="M200,64 C200,73 202,75 210,75 C202,75 200,77 200,86&#xA; C200,77 198,75 190,75 C198,75 200,73 200,64 Z" fill="#fff"></path>
23
+ <circle cx="170" cy="88" r="9" fill="#fff"></circle>
24
+ <circle cx="230" cy="88" r="9" fill="#fff"></circle>
25
+
26
+
27
+ <rect x="184" y="218" width="32" height="34" rx="10" fill="#fff"></rect>
28
+ <rect x="178" y="266" width="28" height="30" rx="9" fill="#fff"></rect>
29
+ <rect x="183" y="310" width="24" height="26" rx="7" fill="#fff"></rect>
30
+
31
+
32
+ <path d="M200,346 L193,368 L172,363 L187,378 L172,393&#xA; L193,388 L200,410 L207,388 L228,393 L213,378&#xA; L228,363 L207,368 Z" fill="#fff"></path>
33
+ </svg>
@@ -0,0 +1,46 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 480" role="img" aria-label="ThreatRecall">
2
+ <title>ThreatRecall</title>
3
+ <defs>
4
+ <linearGradient id="shieldGrad" x1="0" y1="0" x2="0" y2="1">
5
+ <stop offset="0%" stop-color="#8ED1A0"/>
6
+ <stop offset="100%" stop-color="#5EAE78"/>
7
+ </linearGradient>
8
+ </defs>
9
+
10
+ <!-- Shield -->
11
+ <path d="M55 35 H345 a16 16 0 0 1 16 16 V265 c0 96 -71 162 -161 196 c-90 -34 -161 -100 -161 -196 V51 a16 16 0 0 1 16 -16 Z"
12
+ fill="url(#shieldGrad)"/>
13
+
14
+ <!-- Axon recall trail (centered) -->
15
+ <path d="M200 158 C 198 205 190 250 192 275 S 199 345 200 365"
16
+ fill="none" stroke="#FFFFFF" stroke-width="2.5" stroke-linecap="round"
17
+ stroke-dasharray="1.5 7" opacity="0.5"/>
18
+
19
+ <!-- Cell body / nucleus -->
20
+ <circle cx="200" cy="155" r="24" fill="#FFFFFF"/>
21
+
22
+ <!-- Dendrites: symmetric sparkles -->
23
+ <path d="M 128,93 C 128,111.7 131.3,115 150,115 C 131.3,115 128,118.3 128,137 C 128,118.3 124.7,115 106,115 C 124.7,115 128,111.7 128,93 Z" fill="#FFFFFF"/>
24
+ <path d="M 272,93 C 272,111.7 275.3,115 294,115 C 275.3,115 272,118.3 272,137 C 272,118.3 268.7,115 250,115 C 268.7,115 272,111.7 272,93 Z" fill="#FFFFFF"/>
25
+ <path d="M 200,61 C 200,70.35 201.65,72 211,72 C 201.65,72 200,73.65 200,83 C 200,73.65 198.35,72 189,72 C 198.35,72 200,70.35 200,61 Z" fill="#FFFFFF"/>
26
+
27
+ <circle cx="168" cy="85" r="3.5" fill="#FFFFFF"/>
28
+ <circle cx="232" cy="85" r="3.5" fill="#FFFFFF"/>
29
+ <circle cx="112" cy="160" r="2.5" fill="#FFFFFF"/>
30
+ <circle cx="288" cy="160" r="2.5" fill="#FFFFFF"/>
31
+
32
+ <!-- Myelin segments on axon -->
33
+ <rect x="188" y="200" width="24" height="28" rx="8" fill="#FFFFFF"/>
34
+ <rect x="181" y="252" width="22" height="26" rx="7" fill="#FFFFFF"/>
35
+ <rect x="186" y="302" width="19" height="22" rx="6" fill="#FFFFFF"/>
36
+
37
+ <!-- Axon terminal burst -->
38
+ <path d="M 200.0,342.0 L 194.5,360.5 L 175.8,356.0 L 189.0,370.0 L 175.8,384.0 L 194.5,379.5 L 200.0,398.0 L 205.5,379.5 L 224.2,384.0 L 211.0,370.0 L 224.2,356.0 L 205.5,360.5 Z"
39
+ fill="#FFFFFF"/>
40
+
41
+ <!-- Axon terminal branches (symmetric) -->
42
+ <circle cx="155" cy="348" r="3" fill="#FFFFFF"/>
43
+ <circle cx="245" cy="348" r="3" fill="#FFFFFF"/>
44
+ <circle cx="160" cy="408" r="2.5" fill="#FFFFFF"/>
45
+ <circle cx="240" cy="408" r="2.5" fill="#FFFFFF"/>
46
+ </svg>
@@ -0,0 +1,41 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 320" role="img" aria-label="ThreatRecall">
2
+ <title>ThreatRecall monogram lockup</title>
3
+ <defs>
4
+ <linearGradient id="shieldGradMono" x1="0" y1="0" x2="0" y2="1">
5
+ <stop offset="0%" stop-color="#8ED1A0"/>
6
+ <stop offset="100%" stop-color="#5EAE78"/>
7
+ </linearGradient>
8
+ </defs>
9
+
10
+ <!-- Shield acts as capital T -->
11
+ <g transform="translate(30, 52) scale(0.4464)">
12
+ <path d="M55 35 H345 a16 16 0 0 1 16 16 V265 c0 96 -71 162 -161 196 c-90 -34 -161 -100 -161 -196 V51 a16 16 0 0 1 16 -16 Z" fill="url(#shieldGradMono)"/>
13
+ <path d="M200 158 C 198 205 190 250 192 275 S 199 345 200 365" fill="none" stroke="#FFFFFF" stroke-width="2.5" stroke-linecap="round" stroke-dasharray="1.5 7" opacity="0.5"/>
14
+ <circle cx="200" cy="155" r="24" fill="#FFFFFF"/>
15
+ <path d="M 128,93 C 128,111.7 131.3,115 150,115 C 131.3,115 128,118.3 128,137 C 128,118.3 124.7,115 106,115 C 124.7,115 128,111.7 128,93 Z" fill="#FFFFFF"/>
16
+ <path d="M 272,93 C 272,111.7 275.3,115 294,115 C 275.3,115 272,118.3 272,137 C 272,118.3 268.7,115 250,115 C 268.7,115 272,111.7 272,93 Z" fill="#FFFFFF"/>
17
+ <path d="M 200,61 C 200,70.35 201.65,72 211,72 C 201.65,72 200,73.65 200,83 C 200,73.65 198.35,72 189,72 C 198.35,72 200,70.35 200,61 Z" fill="#FFFFFF"/>
18
+ <circle cx="168" cy="85" r="3.5" fill="#FFFFFF"/>
19
+ <circle cx="232" cy="85" r="3.5" fill="#FFFFFF"/>
20
+ <circle cx="112" cy="160" r="2.5" fill="#FFFFFF"/>
21
+ <circle cx="288" cy="160" r="2.5" fill="#FFFFFF"/>
22
+ <rect x="188" y="200" width="24" height="28" rx="8" fill="#FFFFFF"/>
23
+ <rect x="181" y="252" width="22" height="26" rx="7" fill="#FFFFFF"/>
24
+ <rect x="186" y="302" width="19" height="22" rx="6" fill="#FFFFFF"/>
25
+ <path d="M 200.0,342.0 L 194.5,360.5 L 175.8,356.0 L 189.0,370.0 L 175.8,384.0 L 194.5,379.5 L 200.0,398.0 L 205.5,379.5 L 224.2,384.0 L 211.0,370.0 L 224.2,356.0 L 205.5,360.5 Z" fill="#FFFFFF"/>
26
+ <circle cx="155" cy="348" r="3" fill="#FFFFFF"/>
27
+ <circle cx="245" cy="348" r="3" fill="#FFFFFF"/>
28
+ <circle cx="160" cy="408" r="2.5" fill="#FFFFFF"/>
29
+ <circle cx="240" cy="408" r="2.5" fill="#FFFFFF"/>
30
+ </g>
31
+
32
+ <!-- Wordmark beginning at "h" since shield is the T -->
33
+ <g font-family="'Inter', 'Helvetica Neue', Arial, sans-serif">
34
+ <text x="210" y="200" font-size="130" font-weight="700" fill="#1F2937" letter-spacing="-4">
35
+ <tspan>hreat</tspan><tspan fill="#5EAE78" font-weight="800">Recall</tspan>
36
+ </text>
37
+ <text x="214" y="240" font-size="22" font-weight="500" fill="#6B7280" letter-spacing="4">
38
+ THREAT INTELLIGENCE . MEMORY . RECALL
39
+ </text>
40
+ </g>
41
+ </svg>
@@ -0,0 +1,39 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 320" role="img" aria-label="ThreatRecall">
2
+ <title>ThreatRecall lockup</title>
3
+ <defs>
4
+ <linearGradient id="shieldGrad2" x1="0" y1="0" x2="0" y2="1">
5
+ <stop offset="0%" stop-color="#8ED1A0"/>
6
+ <stop offset="100%" stop-color="#5EAE78"/>
7
+ </linearGradient>
8
+ </defs>
9
+
10
+ <g transform="translate(40, 20) scale(0.58)">
11
+ <path d="M55 35 H345 a16 16 0 0 1 16 16 V265 c0 96 -71 162 -161 196 c-90 -34 -161 -100 -161 -196 V51 a16 16 0 0 1 16 -16 Z" fill="url(#shieldGrad2)"/>
12
+ <path d="M200 158 C 198 205 190 250 192 275 S 199 345 200 365" fill="none" stroke="#FFFFFF" stroke-width="2.5" stroke-linecap="round" stroke-dasharray="1.5 7" opacity="0.5"/>
13
+ <circle cx="200" cy="155" r="24" fill="#FFFFFF"/>
14
+ <path d="M 128,93 C 128,111.7 131.3,115 150,115 C 131.3,115 128,118.3 128,137 C 128,118.3 124.7,115 106,115 C 124.7,115 128,111.7 128,93 Z" fill="#FFFFFF"/>
15
+ <path d="M 272,93 C 272,111.7 275.3,115 294,115 C 275.3,115 272,118.3 272,137 C 272,118.3 268.7,115 250,115 C 268.7,115 272,111.7 272,93 Z" fill="#FFFFFF"/>
16
+ <path d="M 200,61 C 200,70.35 201.65,72 211,72 C 201.65,72 200,73.65 200,83 C 200,73.65 198.35,72 189,72 C 198.35,72 200,70.35 200,61 Z" fill="#FFFFFF"/>
17
+ <circle cx="168" cy="85" r="3.5" fill="#FFFFFF"/>
18
+ <circle cx="232" cy="85" r="3.5" fill="#FFFFFF"/>
19
+ <circle cx="112" cy="160" r="2.5" fill="#FFFFFF"/>
20
+ <circle cx="288" cy="160" r="2.5" fill="#FFFFFF"/>
21
+ <rect x="188" y="200" width="24" height="28" rx="8" fill="#FFFFFF"/>
22
+ <rect x="181" y="252" width="22" height="26" rx="7" fill="#FFFFFF"/>
23
+ <rect x="186" y="302" width="19" height="22" rx="6" fill="#FFFFFF"/>
24
+ <path d="M 200.0,342.0 L 194.5,360.5 L 175.8,356.0 L 189.0,370.0 L 175.8,384.0 L 194.5,379.5 L 200.0,398.0 L 205.5,379.5 L 224.2,384.0 L 211.0,370.0 L 224.2,356.0 L 205.5,360.5 Z" fill="#FFFFFF"/>
25
+ <circle cx="155" cy="348" r="3" fill="#FFFFFF"/>
26
+ <circle cx="245" cy="348" r="3" fill="#FFFFFF"/>
27
+ <circle cx="160" cy="408" r="2.5" fill="#FFFFFF"/>
28
+ <circle cx="240" cy="408" r="2.5" fill="#FFFFFF"/>
29
+ </g>
30
+
31
+ <g font-family="'Inter', 'Helvetica Neue', Arial, sans-serif">
32
+ <text x="310" y="175" font-size="92" font-weight="700" fill="#1F2937" letter-spacing="-2">
33
+ <tspan>Threat</tspan><tspan fill="#5EAE78" font-weight="800">Recall</tspan>
34
+ </text>
35
+ <text x="313" y="215" font-size="22" font-weight="500" fill="#6B7280" letter-spacing="4">
36
+ THREAT INTELLIGENCE . MEMORY . RECALL
37
+ </text>
38
+ </g>
39
+ </svg>
@@ -0,0 +1,29 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 480" role="img" aria-label="ThreatRecall">
2
+ <title>ThreatRecall monochrome</title>
3
+
4
+ <path d="M55 35 H345 a16 16 0 0 1 16 16 V265 c0 96 -71 162 -161 196 c-90 -34 -161 -100 -161 -196 V51 a16 16 0 0 1 16 -16 Z"
5
+ fill="#6DB97F"/>
6
+
7
+ <circle cx="200" cy="155" r="24" fill="#FFFFFF"/>
8
+
9
+ <path d="M 128,93 C 128,111.7 131.3,115 150,115 C 131.3,115 128,118.3 128,137 C 128,118.3 124.7,115 106,115 C 124.7,115 128,111.7 128,93 Z" fill="#FFFFFF"/>
10
+ <path d="M 272,93 C 272,111.7 275.3,115 294,115 C 275.3,115 272,118.3 272,137 C 272,118.3 268.7,115 250,115 C 268.7,115 272,111.7 272,93 Z" fill="#FFFFFF"/>
11
+ <path d="M 200,61 C 200,70.35 201.65,72 211,72 C 201.65,72 200,73.65 200,83 C 200,73.65 198.35,72 189,72 C 198.35,72 200,70.35 200,61 Z" fill="#FFFFFF"/>
12
+
13
+ <circle cx="168" cy="85" r="3.5" fill="#FFFFFF"/>
14
+ <circle cx="232" cy="85" r="3.5" fill="#FFFFFF"/>
15
+ <circle cx="112" cy="160" r="2.5" fill="#FFFFFF"/>
16
+ <circle cx="288" cy="160" r="2.5" fill="#FFFFFF"/>
17
+
18
+ <rect x="188" y="200" width="24" height="28" rx="8" fill="#FFFFFF"/>
19
+ <rect x="181" y="252" width="22" height="26" rx="7" fill="#FFFFFF"/>
20
+ <rect x="186" y="302" width="19" height="22" rx="6" fill="#FFFFFF"/>
21
+
22
+ <path d="M 200.0,342.0 L 194.5,360.5 L 175.8,356.0 L 189.0,370.0 L 175.8,384.0 L 194.5,379.5 L 200.0,398.0 L 205.5,379.5 L 224.2,384.0 L 211.0,370.0 L 224.2,356.0 L 205.5,360.5 Z"
23
+ fill="#FFFFFF"/>
24
+
25
+ <circle cx="155" cy="348" r="3" fill="#FFFFFF"/>
26
+ <circle cx="245" cy="348" r="3" fill="#FFFFFF"/>
27
+ <circle cx="160" cy="408" r="2.5" fill="#FFFFFF"/>
28
+ <circle cx="240" cy="408" r="2.5" fill="#FFFFFF"/>
29
+ </svg>
@@ -0,0 +1,105 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 680 760" role="img" aria-labelledby="tt td">
2
+ <title id="tt">ZettelForge architecture</title>
3
+ <desc id="td">Four-stage CTI memory pipeline drawn as a neuron-chain: ingestion, enrichment, retrieval, synthesis, with pluggable storage and optional extensions.</desc>
4
+ <defs>
5
+ <filter id="pulse" x="-50%" y="-50%" width="200%" height="200%">
6
+ <feGaussianBlur stdDeviation="3" result="b"></feGaussianBlur>
7
+ <feMerge><feMergeNode in="b"></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge>
8
+ </filter>
9
+ </defs>
10
+
11
+ <rect width="680" height="760" fill="#FFFFFF"></rect>
12
+
13
+
14
+ <text x="40" y="42" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="11" font-weight="600" letter-spacing="0.08em" fill="#6B7280">ZETTELFORGE / ARCHITECTURE</text>
15
+ <text x="40" y="64" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="18" font-weight="600" letter-spacing="-0.01em" fill="#1F2937">Signal memory — a recall loop</text>
16
+ <text x="40" y="82" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="12" fill="#6B7280">Four-stage pipeline; each stage is a node, the axon is the dataflow.</text>
17
+ <line x1="40" y1="98" x2="640" y2="98" stroke="#E5E9F0"></line>
18
+
19
+ <text x="40" y="126" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="11" font-weight="600" letter-spacing="0.08em" fill="#6B7280">SOURCE</text>
20
+ <text x="40" y="144" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#1F2937">reports · alerts · notes · IOCs</text>
21
+
22
+
23
+ <path d="M140 196 C 128 182 108 178 96 188" stroke="#C9D1D9" fill="none"></path>
24
+ <path d="M140 196 C 152 182 172 178 184 188" stroke="#C9D1D9" fill="none"></path>
25
+ <circle cx="96" cy="188" r="2" fill="#1F2937"></circle>
26
+ <circle cx="184" cy="188" r="2" fill="#1F2937"></circle>
27
+ <circle cx="140" cy="220" r="28" fill="#F4F6FA" stroke="#C9D1D9" stroke-width="1.25"></circle>
28
+ <circle cx="140" cy="220" r="6" fill="#1F2937"></circle>
29
+ <text x="140" y="252" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="10.5" font-weight="700" letter-spacing="0.12em" fill="#1F2937">01</text>
30
+ <rect x="196" y="192" width="444" height="72" rx="8" fill="#FFFFFF" stroke="#E5E9F0"></rect>
31
+ <text x="216" y="218" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="15" font-weight="600" letter-spacing="-0.01em" fill="#1F2937">Ingestion</text>
32
+ <text x="216" y="236" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">MemoryManager → FactExtractor</text>
33
+ <text x="216" y="254" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#1F2937">validate → extract entities → resolve aliases</text>
34
+ <text x="624" y="254" text-anchor="end" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">~45ms</text>
35
+ <path d="M140 252 L140 298" stroke="#C9D1D9" stroke-width="1.5" fill="none" stroke-dasharray="1.5 7" stroke-linecap="round"></path>
36
+
37
+
38
+ <circle cx="140" cy="330" r="28" fill="#F4F6FA" stroke="#C9D1D9" stroke-width="1.25"></circle>
39
+ <circle cx="140" cy="330" r="6" fill="#1F2937"></circle>
40
+ <text x="140" y="362" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="10.5" font-weight="700" letter-spacing="0.12em" fill="#1F2937">02</text>
41
+ <rect x="196" y="302" width="444" height="72" rx="8" fill="#FFFFFF" stroke="#E5E9F0"></rect>
42
+ <text x="216" y="328" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="15" font-weight="600" letter-spacing="-0.01em" fill="#1F2937">Enrichment</text>
43
+ <text x="216" y="346" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">MemoryUpdater · background</text>
44
+ <text x="216" y="364" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#1F2937">causal triples · neighbor refinement · HGAM</text>
45
+ <path d="M140 358 L140 404" stroke="#C9D1D9" stroke-width="1.5" fill="none" stroke-dasharray="1.5 7" stroke-linecap="round"></path>
46
+
47
+
48
+ <path d="M140 438 C 116 430 96 432 80 442" stroke="#5EAE78" stroke-width="1.25" fill="none" opacity="0.85"></path>
49
+ <path d="M140 438 C 164 430 184 432 200 442" stroke="#5EAE78" stroke-width="1.25" fill="none" opacity="0.85"></path>
50
+ <path d="M140 438 C 118 452 98 460 84 468" stroke="#5EAE78" stroke-width="1.25" fill="none" opacity="0.85"></path>
51
+ <path d="M140 438 C 162 452 182 460 196 468" stroke="#5EAE78" stroke-width="1.25" fill="none" opacity="0.85"></path>
52
+ <circle cx="80" cy="442" r="2.25" fill="#5EAE78" filter="url(#pulse)"></circle>
53
+ <circle cx="200" cy="442" r="2.25" fill="#5EAE78" filter="url(#pulse)"></circle>
54
+ <circle cx="84" cy="468" r="1.75" fill="#5EAE78"></circle>
55
+ <circle cx="196" cy="468" r="1.75" fill="#5EAE78"></circle>
56
+ <circle cx="140" cy="438" r="30" fill="#F4F6FA" stroke="#5EAE78" stroke-width="1.5" filter="url(#pulse)"></circle>
57
+ <circle cx="140" cy="438" r="6" fill="#5EAE78" filter="url(#pulse)"></circle>
58
+ <text x="140" y="472" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="10.5" font-weight="700" letter-spacing="0.12em" fill="#5EAE78">03</text>
59
+ <rect x="196" y="410" width="444" height="72" rx="8" fill="#FFFFFF" stroke="#5EAE78" stroke-width="1.25"></rect>
60
+ <text x="216" y="436" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="15" font-weight="600" letter-spacing="-0.01em" fill="#1F2937">Retrieval</text>
61
+ <text x="216" y="454" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">BlendedRetriever</text>
62
+ <text x="216" y="472" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#1F2937">intent · vector + graph BFS · temporal · rerank</text>
63
+
64
+ <rect x="568" y="418" width="56" height="18" rx="9" fill="#5EAE78"></rect>
65
+ <circle cx="578" cy="427" r="2.25" fill="#FFFFFF"></circle>
66
+ <text x="596" y="431" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="10" font-weight="700" letter-spacing="0.14em" fill="#FFFFFF">LIVE</text>
67
+ <path d="M140 468 L140 514" stroke="#5EAE78" stroke-width="1.75" fill="none" stroke-dasharray="1.5 7" stroke-linecap="round"></path>
68
+
69
+
70
+ <circle cx="140" cy="548" r="28" fill="#F4F6FA" stroke="#C9D1D9" stroke-width="1.25"></circle>
71
+ <circle cx="140" cy="548" r="6" fill="#1F2937"></circle>
72
+ <text x="140" y="580" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="10.5" font-weight="700" letter-spacing="0.12em" fill="#1F2937">04</text>
73
+ <line x1="140" y1="576" x2="140" y2="592" stroke="#C9D1D9"></line>
74
+ <line x1="130" y1="574" x2="122" y2="590" stroke="#C9D1D9"></line>
75
+ <line x1="150" y1="574" x2="158" y2="590" stroke="#C9D1D9"></line>
76
+ <rect x="196" y="520" width="444" height="72" rx="8" fill="#FFFFFF" stroke="#E5E9F0"></rect>
77
+ <text x="216" y="546" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="15" font-weight="600" letter-spacing="-0.01em" fill="#1F2937">Synthesis</text>
78
+ <text x="216" y="564" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">ContextInjector → RAG-as-answer</text>
79
+ <text x="216" y="582" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#1F2937">quality-validated · grounded to sources</text>
80
+ <text x="624" y="582" text-anchor="end" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">66.9% LOCOMO · +33%</text>
81
+
82
+
83
+ <line x1="40" y1="626" x2="640" y2="626" stroke="#E5E9F0"></line>
84
+ <text x="40" y="648" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="11" font-weight="600" letter-spacing="0.08em" fill="#6B7280">PLUGGABLE STORAGE</text>
85
+ <text x="40" y="664" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#6B7280">StorageBackend ABC · 33 methods · ZETTELFORGE_BACKEND</text>
86
+
87
+ <rect x="40" y="676" width="292" height="48" rx="8" fill="#FFFFFF" stroke="#E5E9F0"></rect>
88
+ <text x="56" y="698" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="13.5" font-weight="600" fill="#1F2937">SQLite</text>
89
+ <text x="110" y="698" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">default</text>
90
+ <text x="56" y="714" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="12" fill="#6B7280">WAL · ACID · notes, graph, entities</text>
91
+
92
+ <rect x="348" y="676" width="292" height="48" rx="8" fill="#FFFFFF" stroke="#E5E9F0"></rect>
93
+ <text x="364" y="698" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="13.5" font-weight="600" fill="#1F2937">LanceDB</text>
94
+ <text x="422" y="698" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="11.5" font-weight="500" fill="#9CA3AF">vectors</text>
95
+ <text x="364" y="714" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="12" fill="#6B7280">768-dim · nomic-embed-text-v1.5-Q</text>
96
+
97
+ <text x="40" y="744" font-family="Inter, system-ui, -apple-system, &#39;Segoe UI&#39;, sans-serif" font-size="11" font-weight="600" letter-spacing="0.08em" fill="#6B7280">EXTENSIONS</text>
98
+ <g transform="translate(140, 732)">
99
+ <rect x="0" y="0" width="98" height="18" rx="9" fill="#F4F6FA" stroke="#E5E9F0"></rect><text x="49" y="12.5" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="12" font-weight="600" fill="#1F2937">TypeDB STIX 2.1</text>
100
+ <rect x="106" y="0" width="80" height="18" rx="9" fill="#F4F6FA" stroke="#E5E9F0"></rect><text x="146" y="12.5" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="12" font-weight="600" fill="#1F2937">OAuth/JWT</text>
101
+ <rect x="194" y="0" width="92" height="18" rx="9" fill="#F4F6FA" stroke="#E5E9F0"></rect><text x="240" y="12.5" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="12" font-weight="600" fill="#1F2937">OpenCTI sync</text>
102
+ <rect x="294" y="0" width="86" height="18" rx="9" fill="#F4F6FA" stroke="#E5E9F0"></rect><text x="337" y="12.5" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="12" font-weight="600" fill="#1F2937">Sigma rules</text>
103
+ <rect x="388" y="0" width="88" height="18" rx="9" fill="#F4F6FA" stroke="#E5E9F0"></rect><text x="432" y="12.5" text-anchor="middle" font-family="&#39;JetBrains Mono&#39;, ui-monospace, Menlo, Consolas, monospace" font-size="12" font-weight="600" fill="#1F2937">MCP server</text>
104
+ </g>
105
+ </svg>