zettelforge 2.4.2__tar.gz → 2.5.1__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 (322) hide show
  1. zettelforge-2.5.1/.github/CODEOWNERS +8 -0
  2. zettelforge-2.5.1/.github/workflows/ci.yml +158 -0
  3. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/workflows/docs.yml +2 -2
  4. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/workflows/publish.yml +3 -3
  5. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/workflows/snyk-security.yml +13 -6
  6. {zettelforge-2.4.2 → zettelforge-2.5.1}/CHANGELOG.md +114 -0
  7. zettelforge-2.5.1/CODEOWNERS +13 -0
  8. {zettelforge-2.4.2 → zettelforge-2.5.1}/CONTRIBUTING.md +8 -2
  9. {zettelforge-2.4.2 → zettelforge-2.5.1}/PKG-INFO +12 -1
  10. zettelforge-2.5.1/SECURITY.md +75 -0
  11. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/locomo_benchmark.py +94 -19
  12. zettelforge-2.5.1/benchmarks/locomo_results.json +287 -0
  13. {zettelforge-2.4.2 → zettelforge-2.5.1}/config.default.yaml +72 -4
  14. zettelforge-2.5.1/docs/THREAT_MODEL.md +248 -0
  15. zettelforge-2.5.1/docs/how-to/configure-pii.md +217 -0
  16. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/configure-typedb.md +1 -1
  17. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/integrate-llm-agent.md +2 -0
  18. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/upgrade.md +45 -5
  19. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/index.md +32 -10
  20. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/configuration.md +139 -24
  21. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-009-enrichment-pipeline-v2.md +66 -3
  22. zettelforge-2.5.1/docs/rfcs/RFC-011-local-llm-backend-config.md +435 -0
  23. zettelforge-2.5.1/docs/rfcs/RFC-012-litellm-unified-provider.md +369 -0
  24. zettelforge-2.5.1/docs/rfcs/RFC-013-presidio-pii-detection.md +517 -0
  25. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-24-phase-0.5-attribution-prelim.md +6 -3
  26. zettelforge-2.5.1/docs/superpowers/research/2026-04-25-graph-retriever-silence.md +117 -0
  27. zettelforge-2.5.1/docs/superpowers/research/2026-04-25-phase-0.5-attribution.md +230 -0
  28. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/tutorials/01-quickstart.md +12 -2
  29. zettelforge-2.5.1/governance/controls.yaml +125 -0
  30. {zettelforge-2.4.2 → zettelforge-2.5.1}/pyproject.toml +49 -2
  31. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/__init__.py +34 -34
  32. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/alias_resolver.py +3 -4
  33. zettelforge-2.5.1/src/zettelforge/blended_retriever.py +128 -0
  34. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/cache.py +4 -4
  35. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/config.py +74 -13
  36. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/consolidation.py +30 -30
  37. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/demo.py +1 -1
  38. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/detection/base.py +11 -11
  39. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/detection/explainer.py +3 -3
  40. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/entity_indexer.py +118 -56
  41. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/extensions.py +2 -2
  42. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/fact_extractor.py +17 -4
  43. zettelforge-2.5.1/src/zettelforge/governance_validator.py +166 -0
  44. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/graph_retriever.py +7 -8
  45. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/integrations/langchain_retriever.py +5 -5
  46. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/intent_classifier.py +4 -5
  47. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/json_parse.py +1 -2
  48. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/knowledge_graph.py +103 -49
  49. zettelforge-2.5.1/src/zettelforge/lance_maintenance.py +242 -0
  50. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/llm_client.py +40 -17
  51. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/llm_providers/__init__.py +18 -7
  52. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/llm_providers/base.py +2 -2
  53. zettelforge-2.5.1/src/zettelforge/llm_providers/litellm_provider.py +141 -0
  54. zettelforge-2.5.1/src/zettelforge/llm_providers/local_provider.py +332 -0
  55. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/llm_providers/mock_provider.py +3 -3
  56. zettelforge-2.5.1/src/zettelforge/llm_providers/ollama_provider.py +129 -0
  57. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/llm_providers/registry.py +3 -4
  58. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/log.py +25 -4
  59. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/mcp/server.py +2 -3
  60. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/memory_evolver.py +23 -8
  61. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/memory_manager.py +117 -57
  62. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/memory_store.py +80 -24
  63. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/memory_updater.py +5 -6
  64. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/note_constructor.py +6 -6
  65. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/note_schema.py +23 -24
  66. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/observability.py +2 -2
  67. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/ocsf.py +41 -18
  68. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/ontology.py +37 -41
  69. zettelforge-2.5.1/src/zettelforge/pii_validator.py +218 -0
  70. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/retry.py +4 -2
  71. zettelforge-2.5.1/src/zettelforge/scripts/compact_lance.py +309 -0
  72. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/scripts/human_eval_sampler.py +6 -6
  73. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/scripts/telemetry_aggregator.py +17 -17
  74. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/scripts/telemetry_dashboard.py +10 -10
  75. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/entities.py +8 -8
  76. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/ingest.py +4 -4
  77. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/tags.py +2 -3
  78. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sqlite_backend.py +32 -31
  79. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/storage_backend.py +23 -22
  80. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/synthesis_generator.py +10 -11
  81. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/synthesis_validator.py +3 -4
  82. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/telemetry.py +25 -25
  83. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/vector_memory.py +37 -22
  84. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/vector_retriever.py +89 -35
  85. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/entities.py +9 -9
  86. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/ingest.py +6 -8
  87. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_blended_retriever.py +68 -5
  88. zettelforge-2.5.1/tests/test_entity_indexer_races.py +189 -0
  89. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_governance_spec_drift.py +25 -10
  90. zettelforge-2.5.1/tests/test_kg_edge_schema.py +135 -0
  91. zettelforge-2.5.1/tests/test_lance_maintenance.py +280 -0
  92. zettelforge-2.5.1/tests/test_llm_providers.py +725 -0
  93. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_logging_compliance.py +88 -0
  94. zettelforge-2.5.1/tests/test_pii_validator.py +341 -0
  95. zettelforge-2.4.2/.github/CODEOWNERS +0 -4
  96. zettelforge-2.4.2/.github/workflows/ci.yml +0 -118
  97. zettelforge-2.4.2/CODEOWNERS +0 -4
  98. zettelforge-2.4.2/SECURITY.md +0 -157
  99. zettelforge-2.4.2/benchmarks/locomo_results.json +0 -962
  100. zettelforge-2.4.2/governance/controls.yaml +0 -59
  101. zettelforge-2.4.2/src/zettelforge/blended_retriever.py +0 -47
  102. zettelforge-2.4.2/src/zettelforge/governance_validator.py +0 -61
  103. zettelforge-2.4.2/src/zettelforge/llm_providers/local_provider.py +0 -96
  104. zettelforge-2.4.2/src/zettelforge/llm_providers/ollama_provider.py +0 -69
  105. zettelforge-2.4.2/tests/test_llm_providers.py +0 -333
  106. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  107. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  108. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/SECURITY.md +0 -0
  109. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/dependabot.yml +0 -0
  110. {zettelforge-2.4.2 → zettelforge-2.5.1}/.github/pull_request_template.md +0 -0
  111. {zettelforge-2.4.2 → zettelforge-2.5.1}/.gitignore +0 -0
  112. {zettelforge-2.4.2 → zettelforge-2.5.1}/ARCHITECTURE.md +0 -0
  113. {zettelforge-2.4.2 → zettelforge-2.5.1}/CODE_OF_CONDUCT.md +0 -0
  114. {zettelforge-2.4.2 → zettelforge-2.5.1}/Dockerfile +0 -0
  115. {zettelforge-2.4.2 → zettelforge-2.5.1}/GOVERNANCE.md +0 -0
  116. {zettelforge-2.4.2 → zettelforge-2.5.1}/LICENSE +0 -0
  117. {zettelforge-2.4.2 → zettelforge-2.5.1}/MANIFEST.in +0 -0
  118. {zettelforge-2.4.2 → zettelforge-2.5.1}/README.md +0 -0
  119. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/BENCHMARK_REPORT.md +0 -0
  120. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/LOCOMO_BENCHMARK_COMPARISON.md +0 -0
  121. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/auto_ralph.py +0 -0
  122. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/benchmark_harness.py +0 -0
  123. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/cti_benchmark_v2.py +0 -0
  124. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/cti_retrieval_benchmark.py +0 -0
  125. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/cti_retrieval_results.json +0 -0
  126. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/cti_v2_results.json +0 -0
  127. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/ctibench_benchmark.py +0 -0
  128. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/ctibench_results.json +0 -0
  129. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/dataset.json +0 -0
  130. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/enterprise-attack.json +0 -0
  131. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/evolve_benchmark.py +0 -0
  132. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/evolve_results.json +0 -0
  133. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/graph_test.py +0 -0
  134. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/locomo_results_v1.3.0_baseline.json +0 -0
  135. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/memoryagentbench.py +0 -0
  136. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/memoryagentbench_results.json +0 -0
  137. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/mempalace_benchmark.py +0 -0
  138. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/mempalace_results.json +0 -0
  139. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/naive_memory.py +0 -0
  140. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/opencti_benchmark.py +0 -0
  141. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/ragas_benchmark.py +0 -0
  142. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/ragas_cti_results.json +0 -0
  143. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/ragas_results.json +0 -0
  144. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/results/benchmark_report.md +0 -0
  145. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/results/ralph_optimization_log.json +0 -0
  146. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/scale_benchmark.py +0 -0
  147. {zettelforge-2.4.2 → zettelforge-2.5.1}/benchmarks/scale_results.json +0 -0
  148. {zettelforge-2.4.2 → zettelforge-2.5.1}/config.example.yaml +0 -0
  149. {zettelforge-2.4.2 → zettelforge-2.5.1}/docker/docker-compose.yml +0 -0
  150. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/.well-known/security.txt +0 -0
  151. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/CNAME +0 -0
  152. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/architecture-diagram.mmd +0 -0
  153. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/archive/PACKAGE_SUMMARY.md +0 -0
  154. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/archive/README.md +0 -0
  155. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/archive/SKILL.md +0 -0
  156. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/ZettelForge_Architecture.mmd +0 -0
  157. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/architecture-overview.mmd +0 -0
  158. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/architecture-read-path.mmd +0 -0
  159. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/architecture-write-path.mmd +0 -0
  160. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/cf-analytics.js +0 -0
  161. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/demo.gif +0 -0
  162. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon-16.png +0 -0
  163. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon-32.png +0 -0
  164. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon-512.png +0 -0
  165. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon-64.png +0 -0
  166. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon-apple-touch.png +0 -0
  167. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon-old.svg +0 -0
  168. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/favicon.svg +0 -0
  169. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/logo.svg +0 -0
  170. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/social-preview.png +0 -0
  171. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/threatrecall-lockup-monogram.svg +0 -0
  172. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/threatrecall-lockup.svg +0 -0
  173. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/threatrecall-logo-flat.svg +0 -0
  174. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/threatrecall-logo-philosophy.md +0 -0
  175. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/threatrecall-logo.png +0 -0
  176. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/threatrecall-mark.png +0 -0
  177. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/zettelforge_architecture-light.svg +0 -0
  178. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/assets/zettelforge_architecture.svg +0 -0
  179. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/brand/brandIdentity.md +0 -0
  180. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/brand/colors_and_type.css +0 -0
  181. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/explanation/architecture.md +0 -0
  182. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/explanation/epistemic-tiers.md +0 -0
  183. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/explanation/stix-in-zettelforge.md +0 -0
  184. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/explanation/two-phase-pipeline.md +0 -0
  185. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/explanation/zettelkasten-philosophy.md +0 -0
  186. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/configure-lancedb.md +0 -0
  187. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/configure-opencti.md +0 -0
  188. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/ingest-news-report.md +0 -0
  189. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/migrate-jsonl-to-sqlite.md +0 -0
  190. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/query-apt-tools.md +0 -0
  191. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/reproduce-benchmarks.md +0 -0
  192. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/resolve-aliases.md +0 -0
  193. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/run-temporal-query.md +0 -0
  194. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/store-threat-actor.md +0 -0
  195. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/how-to/troubleshoot.md +0 -0
  196. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/human-evaluation-rubric.md +0 -0
  197. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/llms.txt +0 -0
  198. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/narrative/2026-04-16-the-memory-problem.md +0 -0
  199. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/overrides/main.html +0 -0
  200. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/architecture-deep-dive.md +0 -0
  201. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/governance-controls.md +0 -0
  202. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/memory-manager-api.md +0 -0
  203. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/module-inventory.md +0 -0
  204. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/retrieval-policies.md +0 -0
  205. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/reference/stix-schema.md +0 -0
  206. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-001-conversational-entity-extractor.md +0 -0
  207. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-002-universal-llm-provider.md +0 -0
  208. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-003-adversarial-review.md +0 -0
  209. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-003-read-path-depth-routing.md +0 -0
  210. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-007-operational-telemetry.md +0 -0
  211. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/rfcs/RFC-010-enrichment-hotfix.md +0 -0
  212. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/stylesheets/brand-tokens.css +0 -0
  213. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/stylesheets/extra.css +0 -0
  214. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/stylesheets/fonts/Neuropol.otf +0 -0
  215. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-09-ctibench-ragas-benchmarks.md +0 -0
  216. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-09-fastembed-local-embeddings.md +0 -0
  217. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-09-hybrid-typedb-lancedb-architecture.md +0 -0
  218. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-09-local-llm-llama-cpp.md +0 -0
  219. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-anti-aversion-cleanup.md +0 -0
  220. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-causal-graph.md +0 -0
  221. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-ctibench-ate-fix.md +0 -0
  222. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-format-stability.md +0 -0
  223. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-memory-evolution.md +0 -0
  224. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-merge-consolidation.md +0 -0
  225. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-persistence-semantics.md +0 -0
  226. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-15-sqlite-migration.md +0 -0
  227. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/2026-04-17-test-suite-audit.md +0 -0
  228. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/research/README.md +0 -0
  229. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/superpowers/specs/2026-04-15-p1-features-prd.md +0 -0
  230. {zettelforge-2.4.2 → zettelforge-2.5.1}/docs/tutorials/02-first-cti-report.md +0 -0
  231. {zettelforge-2.4.2 → zettelforge-2.5.1}/examples/athf_bridge.py +0 -0
  232. {zettelforge-2.4.2 → zettelforge-2.5.1}/examples/mcp_claude_code.md +0 -0
  233. {zettelforge-2.4.2 → zettelforge-2.5.1}/examples/quickstart.py +0 -0
  234. {zettelforge-2.4.2 → zettelforge-2.5.1}/mkdocs.yml +0 -0
  235. {zettelforge-2.4.2 → zettelforge-2.5.1}/scripts/migrate_jsonl_to_sqlite.py +0 -0
  236. {zettelforge-2.4.2 → zettelforge-2.5.1}/scripts/rebuild_index.py +0 -0
  237. {zettelforge-2.4.2 → zettelforge-2.5.1}/scripts/record-demo.sh +0 -0
  238. {zettelforge-2.4.2 → zettelforge-2.5.1}/scripts/typedb-setup.sh +0 -0
  239. {zettelforge-2.4.2 → zettelforge-2.5.1}/scripts/zettelforge-rebuild.service +0 -0
  240. {zettelforge-2.4.2 → zettelforge-2.5.1}/scripts/zettelforge-rebuild.timer +0 -0
  241. {zettelforge-2.4.2 → zettelforge-2.5.1}/server.json +0 -0
  242. {zettelforge-2.4.2 → zettelforge-2.5.1}/skills/claude-code-skill.md +0 -0
  243. {zettelforge-2.4.2 → zettelforge-2.5.1}/skills/openclaw-skill.md +0 -0
  244. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/__main__.py +0 -0
  245. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/backend_factory.py +0 -0
  246. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/detection/__init__.py +1 -1
  247. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/detection/consumers.py +0 -0
  248. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/edition.py +0 -0
  249. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/integrations/__init__.py +0 -0
  250. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/mcp/__init__.py +0 -0
  251. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/mcp/__main__.py +0 -0
  252. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/__init__.py +1 -1
  253. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/cli.py +0 -0
  254. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/parser.py +0 -0
  255. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/schemas/NOTICE.md +0 -0
  256. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/schemas/__init__.py +0 -0
  257. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/schemas/sigma-correlation-rules-schema.json +0 -0
  258. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/schemas/sigma-detection-rule-schema.json +0 -0
  259. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/sigma/schemas/sigma-filters-schema.json +0 -0
  260. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/__init__.py +0 -0
  261. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/cccs_metadata.py +2 -2
  262. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/cli.py +0 -0
  263. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/parser.py +0 -0
  264. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/schemas/CCCS_YARA.yml +0 -0
  265. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/schemas/CCCS_YARA_values.yml +0 -0
  266. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/schemas/NOTICE.md +0 -0
  267. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/schemas/__init__.py +0 -0
  268. {zettelforge-2.4.2 → zettelforge-2.5.1}/src/zettelforge/yara/tags.py +0 -0
  269. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/__init__.py +0 -0
  270. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/benchmark_scale.py +0 -0
  271. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/conftest.py +0 -0
  272. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/sigma/cloud_example.yml +0 -0
  273. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/sigma/correlation_example.yml +0 -0
  274. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/sigma/process_creation_example.yml +0 -0
  275. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/sigma/tagged_example.yml +0 -0
  276. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/yara/malware_hash.yar +0 -0
  277. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/yara/technique_loader.yar +0 -0
  278. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/fixtures/yara/webshell.yar +0 -0
  279. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_basic.py +0 -0
  280. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_causal_extraction.py +0 -0
  281. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_config.py +0 -0
  282. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_consolidation.py +0 -0
  283. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_conversational_entities.py +0 -0
  284. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_core.py +0 -0
  285. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_cti_integration.py +0 -0
  286. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_detection_explainer.py +0 -0
  287. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_detection_rule_entities.py +0 -0
  288. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_edition.py +0 -0
  289. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_embedding.py +0 -0
  290. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_extensions.py +0 -0
  291. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_fact_extractor.py +0 -0
  292. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_governance.py +0 -0
  293. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_graph_retriever.py +0 -0
  294. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_human_eval_sampler.py +0 -0
  295. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_intent_classifier.py +0 -0
  296. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_json_parse.py +0 -0
  297. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_langchain_retriever.py +0 -0
  298. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_llm_client.py +0 -0
  299. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_mcp_server.py +0 -0
  300. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_memory_evolver.py +0 -0
  301. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_memory_updater.py +0 -0
  302. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_performance.py +0 -0
  303. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_recall_integration.py +0 -0
  304. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_sigma_entities.py +0 -0
  305. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_sigma_ingest.py +0 -0
  306. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_sigma_parser.py +0 -0
  307. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_sqlite_backend.py +0 -0
  308. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_sqlite_integration.py +0 -0
  309. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_storage_backend.py +0 -0
  310. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_telemetry_aggregator.py +0 -0
  311. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_telemetry_collector.py +0 -0
  312. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_telemetry_dashboard.py +0 -0
  313. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_telemetry_integration.py +0 -0
  314. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_temporal_graph.py +0 -0
  315. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_two_phase_e2e.py +0 -0
  316. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_typedb_client.py +0 -0
  317. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_yara_entities.py +0 -0
  318. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_yara_ingest.py +0 -0
  319. {zettelforge-2.4.2 → zettelforge-2.5.1}/tests/test_yara_parser.py +0 -0
  320. {zettelforge-2.4.2 → zettelforge-2.5.1}/web/app.py +0 -0
  321. {zettelforge-2.4.2 → zettelforge-2.5.1}/web/auth.py +0 -0
  322. {zettelforge-2.4.2 → zettelforge-2.5.1}/web/mcp_server.py +0 -0
@@ -0,0 +1,8 @@
1
+ # Default rule: require @rolandpg for all changes
2
+ * @rolandpg
3
+
4
+ # Critical security-sensitive paths
5
+ .github/workflows/ @rolandpg
6
+ .github/ @rolandpg
7
+ pyproject.toml @rolandpg
8
+ setup.py @rolandpg
@@ -0,0 +1,158 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ lint:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
20
+ with:
21
+ python-version: '3.12'
22
+
23
+ - name: Install linting tools
24
+ run: pip install ruff
25
+
26
+ - name: Lint with ruff
27
+ run: ruff check src/zettelforge/
28
+
29
+ - name: Format check with ruff
30
+ run: ruff format --check src/zettelforge/
31
+
32
+ # GOV-009 §"Vulnerability Response": runs on every PR, fails on
33
+ # HIGH/CRITICAL. Token-free complement to Snyk (which gates on
34
+ # SNYK_TOKEN being set as a repo secret). Audit H-5.
35
+ pip-audit:
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
39
+ - name: Set up Python
40
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
41
+ with:
42
+ python-version: '3.12'
43
+ - name: Install pip-audit
44
+ run: pip install pip-audit
45
+ - name: Audit dependencies (any reported vuln blocks)
46
+ run: |
47
+ pip install -e ".[dev]" || pip install -e "."
48
+ # pip-audit fails non-zero on any reported vuln. Add
49
+ # --ignore-vuln=CVE-... with a citation when the finding is
50
+ # explicitly accepted per GOV-009 §"Vulnerability Response".
51
+ #
52
+ # CVE-2026-3219: vulnerability in `pip` itself (the package
53
+ # manager), not a project dependency. The runner's pip is
54
+ # supplied by GitHub's setup-python image and is not something
55
+ # ZettelForge's pyproject can pin or upgrade. Risk-accepted
56
+ # because the pip vulnerability surface is exposed during
57
+ # install, not at runtime; CI builds in ephemeral runners with
58
+ # no persistent state. Re-evaluate when GitHub's images ship a
59
+ # patched pip.
60
+ pip-audit --strict --vulnerability-service=osv \
61
+ --ignore-vuln=CVE-2026-3219
62
+
63
+ test:
64
+ runs-on: ubuntu-latest
65
+ needs: lint
66
+ strategy:
67
+ fail-fast: false
68
+ matrix:
69
+ python-version: ['3.12', '3.13']
70
+
71
+ steps:
72
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
73
+
74
+ - name: Set up Python ${{ matrix.python-version }}
75
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
76
+ with:
77
+ python-version: ${{ matrix.python-version }}
78
+
79
+ - name: Install dependencies
80
+ run: |
81
+ python -m pip install --upgrade pip
82
+ # If [dev] install fails, fall back to bare install + manually
83
+ # add the pytest deps. Parenthesizing the fallback prevents shell
84
+ # precedence from running the "pytest pytest-cov pytest-asyncio"
85
+ # step when [dev] already succeeded (audit L-4).
86
+ pip install -e ".[dev]" || (pip install -e "." && pip install pytest pytest-cov pytest-asyncio)
87
+
88
+ - name: Pre-download fastembed model
89
+ run: |
90
+ python -c "from fastembed import TextEmbedding; TextEmbedding('nomic-ai/nomic-embed-text-v1.5-Q')"
91
+
92
+ - name: Test with pytest
93
+ env:
94
+ ZETTELFORGE_BACKEND: sqlite
95
+ ZETTELFORGE_EMBEDDING_PROVIDER: fastembed
96
+ run: |
97
+ # GOV-007 §"Coverage Requirements" mandates ≥80% line / ≥70% branch.
98
+ # We start the ratchet at 67 (matches governance/controls.yaml's
99
+ # current declaration) so today's pipeline does not break, and #51
100
+ # tracks raising it toward 80% across v2.5.x. Audit finding H-2.
101
+ pytest tests/ -v --cov=zettelforge --cov-report=xml --cov-report=term-missing --cov-fail-under=67
102
+
103
+ - name: Upload coverage
104
+ if: matrix.python-version == '3.12'
105
+ uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2
106
+ with:
107
+ file: ./coverage.xml
108
+ fail_ci_if_error: false
109
+
110
+ governance:
111
+ runs-on: ubuntu-latest
112
+ needs: lint
113
+ steps:
114
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
115
+
116
+ - name: Set up Python
117
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
118
+ with:
119
+ python-version: '3.12'
120
+
121
+ - name: Install dependencies
122
+ run: |
123
+ python -m pip install --upgrade pip
124
+ # See "Install dependencies" comment above (audit L-4).
125
+ pip install -e ".[dev]" || (pip install -e "." && pip install pytest pytest-cov)
126
+
127
+ - name: GOV-012 — Logging compliance tests
128
+ env:
129
+ ZETTELFORGE_BACKEND: sqlite
130
+ run: |
131
+ pytest tests/test_logging_compliance.py -v
132
+
133
+ - name: Governance spec-drift check
134
+ run: |
135
+ pytest tests/test_governance_spec_drift.py -v
136
+
137
+ build:
138
+ runs-on: ubuntu-latest
139
+ needs: [test, governance]
140
+
141
+ steps:
142
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
143
+
144
+ - name: Set up Python
145
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
146
+ with:
147
+ python-version: '3.12'
148
+
149
+ - name: Install build dependencies
150
+ run: |
151
+ python -m pip install --upgrade pip
152
+ pip install build twine
153
+
154
+ - name: Build package
155
+ run: python -m build
156
+
157
+ - name: Check package
158
+ run: twine check dist/*
@@ -14,8 +14,8 @@ jobs:
14
14
  deploy:
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
- - uses: actions/checkout@v6
18
- - uses: actions/setup-python@v6
17
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
18
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
19
19
  with:
20
20
  python-version: '3.12'
21
21
  - run: pip install mkdocs-material
@@ -11,10 +11,10 @@ jobs:
11
11
  id-token: write # trusted publishing
12
12
 
13
13
  steps:
14
- - uses: actions/checkout@v6
14
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
15
15
 
16
16
  - name: Set up Python
17
- uses: actions/setup-python@v6
17
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
18
18
  with:
19
19
  python-version: '3.12'
20
20
 
@@ -25,4 +25,4 @@ jobs:
25
25
  run: python -m build
26
26
 
27
27
  - name: Publish to PyPI
28
- uses: pypa/gh-action-pypi-publish@release/v1
28
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b
@@ -17,10 +17,10 @@ jobs:
17
17
  actions: read
18
18
  runs-on: ubuntu-latest
19
19
  steps:
20
- - uses: actions/checkout@v6
20
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
21
21
 
22
22
  - name: Set up Python
23
- uses: actions/setup-python@v6
23
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
24
24
  with:
25
25
  python-version: '3.12'
26
26
 
@@ -30,7 +30,7 @@ jobs:
30
30
  pip install -e ".[dev]" || pip install -e "."
31
31
 
32
32
  - name: Set up Snyk CLI
33
- uses: snyk/actions/setup@master
33
+ uses: snyk/actions/setup@9adf32b1121593767fc3c057af55b55db032dc04
34
34
  env:
35
35
  SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
36
36
 
@@ -44,21 +44,28 @@ jobs:
44
44
  echo "has_token=true" >> "$GITHUB_OUTPUT"
45
45
  fi
46
46
 
47
+ # GOV-009 §"Vulnerability Response" + GOV-011 §"Testing Phase":
48
+ # HIGH/CRITICAL Snyk findings must fail the gate. Audit H-5 found
49
+ # both Snyk steps suffixed with `|| true`, so real findings shipped
50
+ # silently. Now: --severity-threshold=high so MEDIUM stays advisory
51
+ # and only HIGH/CRITICAL break the build. SARIF is still emitted via
52
+ # --sarif-file-output even when the test fails (snyk-code) so the
53
+ # subsequent Upload SARIF step has artifacts to publish.
47
54
  - name: Snyk Code test (SAST)
48
55
  if: steps.check_token.outputs.has_token == 'true'
49
- run: snyk code test --sarif > snyk-code.sarif || true
56
+ run: snyk code test --sarif-file-output=snyk-code.sarif --severity-threshold=high
50
57
  env:
51
58
  SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
52
59
 
53
60
  - name: Snyk Open Source test (SCA)
54
61
  if: steps.check_token.outputs.has_token == 'true'
55
- run: snyk test --all-projects || true
62
+ run: snyk test --all-projects --severity-threshold=high
56
63
  env:
57
64
  SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
58
65
 
59
66
  - name: Upload SARIF to GitHub
60
67
  if: steps.check_token.outputs.has_token == 'true'
61
- uses: github/codeql-action/upload-sarif@v4
68
+ uses: github/codeql-action/upload-sarif@b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61
62
69
  with:
63
70
  sarif_file: snyk-code.sarif
64
71
  continue-on-error: true
@@ -6,6 +6,120 @@ Versioning follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.5.1] - 2026-04-25
10
+
11
+ Hotfix release. Surfaced during the v2.5.0 perf benchmark run.
12
+
13
+ ### Fixed
14
+
15
+ - **`KnowledgeGraph._cache_edge` crashed on legacy-schema edges**.
16
+ Long-running deployments accumulated `kg_edges.jsonl` entries written
17
+ by a now-removed pre-v2.5.x writer that used
18
+ `{source_id, target_id, relation_type}` instead of the canonical
19
+ `{from_node_id, to_node_id, relationship}` keys. The loader hard-failed
20
+ with `KeyError: 'from_node_id'` on the first such row, taking down
21
+ every `recall()` and `synthesize()` that touches the KG. Affects any
22
+ workspace with mixed-schema edge history; observed locally with 189k
23
+ edges where ~80k were the legacy shape.
24
+ `_normalize_edge_schema()` now remaps legacy keys to canonical on load
25
+ and silently drops entries that are still un-normalizable, with a
26
+ count logged at WARNING so operators can see the skip volume.
27
+ Six new regression tests in `tests/test_kg_edge_schema.py` cover
28
+ pass-through, remap, missing-fields, non-dict, mixed-batch, and
29
+ corrupt-JSON cases. The previously-broken environment-dependent
30
+ `test_basic.py::test_ingest_relationship` now passes deterministically.
31
+
32
+ ## [2.5.0] - 2026-04-25
33
+
34
+ Compliance-driven minor release. Closes every CRITICAL and HIGH audit
35
+ finding except H-3 (mypy strict) and the ANN slice of H-1, both of
36
+ which need per-module ratchet plans. Also adds two new optional LLM
37
+ backends, a Presidio PII detector, and supply-chain hardening.
38
+
39
+ ### Added
40
+
41
+ - **RFC-011 — Local LLM backend selection** (#104). New `local_backend`
42
+ config knob picks between `llama-cpp-python` (GGUF) and
43
+ `onnxruntime-genai` (ONNX) at runtime. Both ship as optional extras
44
+ (`pip install zettelforge[local]` or `[local-onnx]`).
45
+ - **RFC-012 — LiteLLM unified provider** (#108). Routes to 100+
46
+ upstream LLM providers via the LiteLLM SDK. Optional extra
47
+ (`pip install zettelforge[litellm]`); the base package never imports
48
+ it unless the SDK is present.
49
+ - **RFC-013 — Microsoft Presidio PII detection** (#118). Optional PII
50
+ validator with three policies (`log` / `redact` / `block`),
51
+ configurable via `governance.pii.*`. CTI allowlist excludes
52
+ `IP_ADDRESS` / `URL` / `DOMAIN_NAME` from detection so legitimate
53
+ threat-intel indicators flow through unmodified. Soft dependency —
54
+ `pip install zettelforge[pii]` to activate; the base package never
55
+ imports `presidio_analyzer` unless the SDK is present.
56
+ - **GOV-009 Snyk SCA + SAST declared in `controls.yaml`** (#114). The
57
+ spec-drift validator now walks every `.github/workflows/*.yml` so
58
+ controls whose CI step lives outside `ci.yml` (Snyk's separate
59
+ workflow) can be honestly declared.
60
+ - **GOV-006 solo-maintainer compensating controls** (#117). New
61
+ `controls.yaml` entry pins the existing CI gates (lint, tests,
62
+ governance spec-drift) as compensating controls for the GOV-006
63
+ two-person review rule that cannot be physically satisfied with one
64
+ human maintainer. CODEOWNERS updated with explanatory comment.
65
+ - **`SECURITY.md` + CODEOWNERS** added to the repo root for vulnerability
66
+ disclosure and review attribution.
67
+
68
+ ### Changed
69
+
70
+ - **All GitHub Actions are now SHA-pinned** (audit H-5 hardening). Every
71
+ `uses: org/repo@vX` reference replaced with `uses: org/repo@<full-sha> # vX.Y.Z`
72
+ to prevent supply-chain attacks via tag rewrites.
73
+ - **Ruff rule set ratcheted to GOV-003 §"Tooling and Automation" minus
74
+ ANN** (#106 + #107 + #109 + #111 + #113). Active `select` list:
75
+ `{E, F, I, W, N, T20, B, UP, SIM, RUF, S}`. Per-line `# noqa: SXXX`
76
+ annotations document each accepted exception (best-effort fallbacks,
77
+ non-crypto RNG, `?`-bound SQL with constant column lists).
78
+ `RUF002`/`RUF003` ignored globally for stylistic en-dash and ×.
79
+ - **CI install-step shell precedence fixed** (#112). The
80
+ `pip install -e ".[dev]" || pip install -e "." && pip install pytest...`
81
+ chain parsed as `(A || B) && C`, so the pytest install ran on
82
+ every success path including when `[dev]` already provided pytest.
83
+ Wrapped the fallback in parentheses.
84
+ - **CONTRIBUTING.md accuracy** (#115). Documents `ruff format`
85
+ (project hasn't used black for a while) and lists what CI actually
86
+ enforces so new contributors have a green-build target.
87
+
88
+ ### Compliance audit closure (`tasks/compliance-audit-2026-04-25.md`)
89
+
90
+ | Severity | Finding | Status |
91
+ |---|---|---|
92
+ | CRITICAL | C-1 branch protection | CLOSED (with required status checks) |
93
+ | CRITICAL | C-2 fabricated `no_hardcoded_secrets` claim | CLOSED (#100) |
94
+ | HIGH | H-1 ruff full select per GOV-003 | CLOSED for {E,F,I,W,N,T20,B,UP,SIM,RUF,S}; ANN ratcheting per-module |
95
+ | HIGH | H-2 coverage threshold not enforced | CLOSED (#100) |
96
+ | HIGH | H-4 GOV-006 / CODEOWNERS solo-maintainer | CLOSED on the zettelforge side (#117); GOV-006 doc amendment in `rolandpg/governance` repo is separate scope |
97
+ | HIGH | H-5 SCA gate + SHA-pinned actions | CLOSED (#102 + #114 + SHA-pin commit) |
98
+ | MEDIUM | M-1 bare `except:` in production | CLOSED (#100) |
99
+ | MEDIUM | M-3 OCSF `timezone_offset` field | CLOSED (#100) |
100
+ | LOW | L-4 CI install-step shell precedence | CLOSED (#112) |
101
+
102
+ Outstanding: H-3 (mypy --strict in CI; needs per-module ratchet plan
103
+ for 393 errors across 38 files), M-2 (rewrite GOV-016 to match the
104
+ YAML-frontmatter practice already in use), M-4 (lock file), H-1 ANN
105
+ ratchet (121 findings across 38 files).
106
+
107
+ ## [2.4.3] - 2026-04-25
108
+
109
+ Patch release. Three small but consequential fixes that landed during the post-v2.4.2 Vigil live-test session, plus the standalone `compact_lance` maintenance script and Nexus's Tier 0/1/2 LLM observability instrumentation.
110
+
111
+ ### Added
112
+
113
+ - **OCSF `metadata.product.version` self-correct** (#96). `ocsf.py:_resolve_product_version()` now prefers the source `pyproject.toml` reachable from `__file__` and falls back to `importlib.metadata.version("zettelforge")`. Editable installs — where `git checkout vX.Y.Z` updates the source tree but not the installed-metadata record — no longer emit stale version strings. Observed live on Vigil 2026-04-24: v2.4.2 source was emitting `product.version=2.4.1` events because the editable-install metadata hadn't been refreshed.
114
+ - **`ZETTELFORGE_LOG_LEVEL` env var honored** (#96). `log.py:get_logger()` now resolves the log level via env var → `config.yaml log.level` → INFO default. Operators can flip DEBUG without editing code or restarting agent boot order. Resolves the "config.yaml `log.level=DEBUG` was dead code" trap hit on Vigil 2026-04-24, where the auto-configure hardcoded INFO and locked `_configured=True` before any caller could read config.
115
+ - **Fastembed preload** (#96). New `vector_memory.preload_embedding_model()` invoked from `MemoryManager.__init__`. Moves the ~800 ms fastembed model-load cost off the first `remember()` and onto agent startup. Best-effort, no-op when `provider != fastembed`. Phase 0.5 measurement: cold `construct=799ms` vs warm `construct=37ms`.
116
+ - **`compact_lance` maintenance script** (#94). New `python -m zettelforge.scripts.compact_lance` for offline LanceDB shard maintenance. Discovers all `<name>.lance/` tables under `<data-dir>/vectordb/`, supports `--dry-run` / `--table` / `--all` / `--mode {compact,optimize}` / `--force`, emits a per-table JSON report with before/after fragment count, on-disk bytes, row count, and elapsed seconds. Operationalized the Phase 0.5 cleanup intervention (see "Vigil incident response" below).
117
+ - **Tier 0/1/2 LLM observability** (#95, Nexus). `ollama_provider.py` now logs every LLM call (model, prompt_chars, response_chars, response_preview, prompt_preview, duration_ms, eval_count, prompt_eval_count, done_reason). `memory_evolver.py` retries log prompt and raw response previews instead of just `neighbor_id`. `fact_extractor.py` empty completions now emit `parse_failed{schema="fact_extraction", reason="empty_completion"}` (`fact_extractor.py:69-71`) instead of silently returning `[]`. `entity_indexer.py` LLM extractions log prompt previews. `structlog.contextvars`-based `trace_id` propagates through `remember()` so every event in a single note's pipeline shares one correlation key.
118
+
119
+ ### Operational notes
120
+
121
+ The 2026-04-24/25 Vigil live-test session — driven by the v2.4.2 Phase 0.5 instrumentation — found and fixed a 5.66 GB LanceDB version-history bloat on Vigil's `notes_cti` shard. `cleanup_old_versions()` shrank it 5.69 GB → 29 MB and collapsed `remember()` p95 from 49.8 s → ~250 ms. Full evidence in `docs/superpowers/research/2026-04-25-phase-0.5-attribution.md`. The periodic-cleanup feature itself ships in v2.5.0 as RFC-009 Phase 1.5; the v2.4.3 `compact_lance` script supports the one-shot operator workflow until then.
122
+
9
123
  ## [2.4.2] - 2026-04-24
10
124
 
11
125
  Patch release bundling the RFC-010 enrichment-pipeline hotfix with the
@@ -0,0 +1,13 @@
1
+ # ZettelForge Code Owners
2
+ # These users are automatically requested for review on PRs.
3
+ #
4
+ # Solo-maintainer mode (see governance/controls.yaml GOV-006): the
5
+ # project currently has one human maintainer, so the GOV-006 §"Approval
6
+ # Requirements" two-person rule cannot be physically satisfied. Until a
7
+ # second maintainer is added, the compensating controls declared under
8
+ # GOV-006 in controls.yaml (CI-green required, lint, governance
9
+ # spec-drift, plus GOV-009 SCA/SAST gates) substitute for a second set
10
+ # of human eyes. The audit trail of compensating controls is recoverable
11
+ # from CI logs and branch-protection settings.
12
+
13
+ * @rolandpg
@@ -18,10 +18,16 @@ No external services (Ollama, TypeDB, Docker) are required for development. Zett
18
18
  2. Make your changes
19
19
  3. Run tests: `pytest tests/ -v`
20
20
  4. Run linting: `ruff check src/zettelforge/`
21
- 5. Run formatting: `black src/zettelforge/`
22
- 6. Commit with clear messages
21
+ 5. Run formatting: `ruff format src/zettelforge/`
22
+ 6. Commit with a Conventional Commits message (see "Commit Messages" below)
23
23
  7. Push and create a pull request
24
24
 
25
+ CI enforces the same `ruff check` and `ruff format --check` invocations
26
+ plus `pytest --cov-fail-under=67`, `pip-audit`, governance spec-drift,
27
+ and Snyk SCA/SAST. The full active rule set is `{E, F, I, W, N, T20,
28
+ B, UP, SIM, RUF, S}` per GOV-003 §"Tooling and Automation"; only ANN
29
+ remains and is being ratcheted per-module.
30
+
25
31
  ## Where to contribute
26
32
 
27
33
  All of `src/zettelforge/` is MIT-licensed and open to contributions.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zettelforge
3
- Version: 2.4.2
3
+ Version: 2.5.1
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
@@ -46,8 +46,19 @@ Provides-Extra: extensions
46
46
  Requires-Dist: zettelforge-enterprise>=2.1.0; extra == 'extensions'
47
47
  Provides-Extra: langchain
48
48
  Requires-Dist: langchain-core>=0.2.0; extra == 'langchain'
49
+ Provides-Extra: litellm
50
+ Requires-Dist: litellm>=1.60.0; extra == 'litellm'
49
51
  Provides-Extra: local
50
52
  Requires-Dist: llama-cpp-python>=0.3.0; extra == 'local'
53
+ Provides-Extra: local-all
54
+ Requires-Dist: llama-cpp-python>=0.3.0; extra == 'local-all'
55
+ Requires-Dist: onnxruntime-genai>=0.4.0; extra == 'local-all'
56
+ Provides-Extra: local-onnx
57
+ Requires-Dist: onnxruntime-genai>=0.4.0; extra == 'local-onnx'
58
+ Provides-Extra: pii
59
+ Requires-Dist: presidio-analyzer>=2.2.0; extra == 'pii'
60
+ Requires-Dist: presidio-anonymizer>=2.2.0; extra == 'pii'
61
+ Requires-Dist: spacy>=3.5.0; extra == 'pii'
51
62
  Provides-Extra: web
52
63
  Requires-Dist: fastapi>=0.100.0; extra == 'web'
53
64
  Requires-Dist: uvicorn>=0.20.0; extra == 'web'
@@ -0,0 +1,75 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ This is a solo-maintainer project. For security-related issues:
6
+ - Open a GitHub Security Advisory in the repository
7
+ - Tag with `security` label
8
+ - Expect acknowledgement within 48 hours
9
+
10
+ ## Supported Versions
11
+
12
+ | Version | Supported |
13
+ |---------|-----------|
14
+ | latest release | ✅ |
15
+ | master branch | ✅ (CI gates) |
16
+ | older releases | ❌ |
17
+
18
+ ## Supply Chain Security
19
+
20
+ This project implements:
21
+ - SHA-pinned GitHub Actions (all third-party actions pinned by commit SHA)
22
+ - PyPI trusted publishing (OIDC, no long-lived tokens)
23
+ - pip-audit on every CI run (HIGH/CRITICAL must pass)
24
+ - Dependabot for weekly dependency updates
25
+ - Snyk SAST scanning on every push/PR
26
+
27
+ ## Known Security Architecture
28
+
29
+ See [THREAT_MODEL.md](docs/THREAT_MODEL.md) for the complete STRIDE threat model.
30
+
31
+ ### Data at Rest
32
+
33
+ - Notes, the knowledge graph, and the entity index are stored in a local SQLite database (WAL mode) under the configured data directory. No encryption at rest is applied by ZettelForge itself -- encrypt the filesystem or volume at the OS level for sensitive deployments.
34
+ - LanceDB vector index files live alongside the SQLite database and carry the same recommendation.
35
+
36
+ ### PII Protection
37
+
38
+ - As of v2.5.0 (RFC-013), optional PII detection via Microsoft Presidio scans content before `remember()` storage. Three modes: log (discovery), redact (compliance), block (strict). Disabled by default. Requires `pip install zettelforge[pii]` to activate.
39
+ - Raw PII text is never written to structured logs. Only entity type and detection score are recorded.
40
+
41
+ ### LLM Provider Security
42
+
43
+ - Four providers: `local` (in-process, no network), `ollama` (localhost HTTP), `litellm` (cloud APIs), `mock` (testing). Each is configurable via `llm.provider` in config.yaml.
44
+ - `local` provider is fully offline. `ollama` runs on localhost only. `litellm` makes outbound HTTPS calls to configured cloud APIs.
45
+ - API keys use `${ENV_VAR}` resolution -- never committed to YAML. Redacted from all log output via `LLMConfig.__repr__`.
46
+ - Provider timeout is configurable (default 60s). LiteLLM provider supports configurable retry count.
47
+
48
+ ### Injection Defenses
49
+
50
+ - As of v2.1.1, all LanceDB query expressions are parameterized. String-interpolated queries were present in v2.1.0 and earlier (see CVE advisory, if issued, or CHANGELOG v2.1.1 P0-3).
51
+
52
+ ### File Locking
53
+
54
+ - As of v2.1.1, all JSONL and entity index write paths use `fcntl.flock()` exclusive locks to prevent concurrent-write corruption.
55
+
56
+ ### Audit Logging
57
+
58
+ - All security-relevant operations emit OCSF v1.3 structured events via `structlog`. Authorization decisions, API activity, and file activity are auditable in any SIEM that ingests JSON logs.
59
+
60
+ ### Air-Gap Deployments
61
+
62
+ - ZettelForge supports fully offline operation (fastembed ONNX + llama-cpp-python). No telemetry or external calls are made in this configuration.
63
+
64
+ ## Disclosure Policy
65
+
66
+ ZettelForge follows a coordinated disclosure model:
67
+
68
+ 1. Reporter submits vulnerability privately via email.
69
+ 2. We acknowledge within 48 hours and begin assessment.
70
+ 3. We develop and test a fix on a private branch.
71
+ 4. We notify the reporter when a fix is ready and agree on a disclosure date.
72
+ 5. We release the fix and publish a security advisory simultaneously.
73
+ 6. We credit the reporter in the advisory (unless they opt out).
74
+
75
+ We ask reporters to give us a reasonable time to fix issues before public disclosure. We will not take legal action against good-faith security researchers who follow this policy.