zettelforge 2.4.1__tar.gz → 2.5.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.
- zettelforge-2.5.0/.github/CODEOWNERS +8 -0
- zettelforge-2.5.0/.github/workflows/ci.yml +158 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/workflows/docs.yml +2 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/workflows/publish.yml +3 -3
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/workflows/snyk-security.yml +13 -6
- {zettelforge-2.4.1 → zettelforge-2.5.0}/CHANGELOG.md +146 -0
- zettelforge-2.5.0/CODEOWNERS +13 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/CONTRIBUTING.md +8 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/PKG-INFO +12 -1
- zettelforge-2.5.0/SECURITY.md +25 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/locomo_benchmark.py +94 -19
- zettelforge-2.5.0/benchmarks/locomo_results.json +287 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/config.default.yaml +72 -4
- zettelforge-2.5.0/docs/how-to/configure-pii.md +217 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/configure-typedb.md +1 -1
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/integrate-llm-agent.md +2 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/upgrade.md +45 -5
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/index.md +32 -10
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/configuration.md +139 -24
- zettelforge-2.5.0/docs/rfcs/RFC-009-enrichment-pipeline-v2.md +737 -0
- zettelforge-2.5.0/docs/rfcs/RFC-010-enrichment-hotfix.md +115 -0
- zettelforge-2.5.0/docs/rfcs/RFC-011-local-llm-backend-config.md +435 -0
- zettelforge-2.5.0/docs/rfcs/RFC-012-litellm-unified-provider.md +369 -0
- zettelforge-2.5.0/docs/rfcs/RFC-013-presidio-pii-detection.md +517 -0
- zettelforge-2.5.0/docs/superpowers/research/2026-04-24-phase-0.5-attribution-prelim.md +123 -0
- zettelforge-2.5.0/docs/superpowers/research/2026-04-25-graph-retriever-silence.md +117 -0
- zettelforge-2.5.0/docs/superpowers/research/2026-04-25-phase-0.5-attribution.md +230 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/tutorials/01-quickstart.md +12 -2
- zettelforge-2.5.0/governance/controls.yaml +117 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/pyproject.toml +49 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/__init__.py +34 -34
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/alias_resolver.py +3 -4
- zettelforge-2.5.0/src/zettelforge/blended_retriever.py +128 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/cache.py +4 -4
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/config.py +74 -13
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/consolidation.py +49 -30
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/demo.py +1 -1
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/detection/base.py +11 -11
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/detection/explainer.py +3 -3
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/entity_indexer.py +118 -56
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/extensions.py +2 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/fact_extractor.py +17 -4
- zettelforge-2.5.0/src/zettelforge/governance_validator.py +166 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/graph_retriever.py +7 -8
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/integrations/langchain_retriever.py +5 -5
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/intent_classifier.py +4 -5
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/json_parse.py +1 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/knowledge_graph.py +34 -37
- zettelforge-2.5.0/src/zettelforge/lance_maintenance.py +242 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/llm_client.py +40 -17
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/llm_providers/__init__.py +18 -7
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/llm_providers/base.py +2 -2
- zettelforge-2.5.0/src/zettelforge/llm_providers/litellm_provider.py +141 -0
- zettelforge-2.5.0/src/zettelforge/llm_providers/local_provider.py +332 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/llm_providers/mock_provider.py +3 -3
- zettelforge-2.5.0/src/zettelforge/llm_providers/ollama_provider.py +129 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/llm_providers/registry.py +3 -4
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/log.py +25 -4
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/mcp/server.py +2 -3
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/memory_evolver.py +23 -8
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/memory_manager.py +145 -58
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/memory_store.py +80 -24
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/memory_updater.py +5 -6
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/note_constructor.py +6 -6
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/note_schema.py +23 -24
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/observability.py +2 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/ocsf.py +41 -18
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/ontology.py +37 -41
- zettelforge-2.5.0/src/zettelforge/pii_validator.py +218 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/retry.py +4 -2
- zettelforge-2.5.0/src/zettelforge/scripts/compact_lance.py +309 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/scripts/human_eval_sampler.py +6 -6
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/scripts/telemetry_aggregator.py +17 -17
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/scripts/telemetry_dashboard.py +10 -10
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/entities.py +8 -8
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/ingest.py +4 -4
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/tags.py +2 -3
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sqlite_backend.py +32 -31
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/storage_backend.py +23 -22
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/synthesis_generator.py +10 -11
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/synthesis_validator.py +3 -4
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/telemetry.py +25 -25
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/vector_memory.py +37 -22
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/vector_retriever.py +89 -35
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/entities.py +9 -9
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/ingest.py +6 -8
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_blended_retriever.py +68 -5
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_consolidation.py +30 -0
- zettelforge-2.5.0/tests/test_entity_indexer_races.py +189 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_governance_spec_drift.py +25 -10
- zettelforge-2.5.0/tests/test_lance_maintenance.py +280 -0
- zettelforge-2.5.0/tests/test_llm_providers.py +725 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_logging_compliance.py +157 -0
- zettelforge-2.5.0/tests/test_pii_validator.py +341 -0
- zettelforge-2.4.1/.github/CODEOWNERS +0 -4
- zettelforge-2.4.1/.github/workflows/ci.yml +0 -118
- zettelforge-2.4.1/CODEOWNERS +0 -4
- zettelforge-2.4.1/SECURITY.md +0 -157
- zettelforge-2.4.1/benchmarks/locomo_results.json +0 -962
- zettelforge-2.4.1/governance/controls.yaml +0 -59
- zettelforge-2.4.1/src/zettelforge/blended_retriever.py +0 -47
- zettelforge-2.4.1/src/zettelforge/governance_validator.py +0 -61
- zettelforge-2.4.1/src/zettelforge/llm_providers/local_provider.py +0 -96
- zettelforge-2.4.1/src/zettelforge/llm_providers/ollama_provider.py +0 -56
- zettelforge-2.4.1/tests/test_llm_providers.py +0 -318
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/SECURITY.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/dependabot.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.github/pull_request_template.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/.gitignore +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/ARCHITECTURE.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/CODE_OF_CONDUCT.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/Dockerfile +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/GOVERNANCE.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/LICENSE +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/MANIFEST.in +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/README.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/BENCHMARK_REPORT.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/LOCOMO_BENCHMARK_COMPARISON.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/auto_ralph.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/benchmark_harness.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/cti_benchmark_v2.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/cti_retrieval_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/cti_retrieval_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/cti_v2_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/ctibench_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/ctibench_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/dataset.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/enterprise-attack.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/evolve_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/evolve_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/graph_test.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/locomo_results_v1.3.0_baseline.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/memoryagentbench.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/memoryagentbench_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/mempalace_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/mempalace_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/naive_memory.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/opencti_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/ragas_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/ragas_cti_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/ragas_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/results/benchmark_report.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/results/ralph_optimization_log.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/scale_benchmark.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/benchmarks/scale_results.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/config.example.yaml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docker/docker-compose.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/.well-known/security.txt +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/CNAME +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/architecture-diagram.mmd +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/archive/PACKAGE_SUMMARY.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/archive/README.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/archive/SKILL.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/ZettelForge_Architecture.mmd +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/architecture-overview.mmd +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/architecture-read-path.mmd +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/architecture-write-path.mmd +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/cf-analytics.js +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/demo.gif +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon-16.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon-32.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon-512.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon-64.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon-apple-touch.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon-old.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/favicon.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/logo.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/social-preview.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/threatrecall-lockup-monogram.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/threatrecall-lockup.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/threatrecall-logo-flat.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/threatrecall-logo-philosophy.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/threatrecall-logo.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/threatrecall-mark.png +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/zettelforge_architecture-light.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/assets/zettelforge_architecture.svg +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/brand/brandIdentity.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/brand/colors_and_type.css +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/explanation/architecture.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/explanation/epistemic-tiers.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/explanation/stix-in-zettelforge.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/explanation/two-phase-pipeline.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/explanation/zettelkasten-philosophy.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/configure-lancedb.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/configure-opencti.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/ingest-news-report.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/migrate-jsonl-to-sqlite.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/query-apt-tools.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/reproduce-benchmarks.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/resolve-aliases.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/run-temporal-query.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/store-threat-actor.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/how-to/troubleshoot.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/human-evaluation-rubric.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/llms.txt +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/narrative/2026-04-16-the-memory-problem.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/overrides/main.html +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/architecture-deep-dive.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/governance-controls.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/memory-manager-api.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/module-inventory.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/retrieval-policies.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/reference/stix-schema.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/rfcs/RFC-001-conversational-entity-extractor.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/rfcs/RFC-002-universal-llm-provider.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/rfcs/RFC-003-adversarial-review.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/rfcs/RFC-003-read-path-depth-routing.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/rfcs/RFC-007-operational-telemetry.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/stylesheets/brand-tokens.css +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/stylesheets/extra.css +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/stylesheets/fonts/Neuropol.otf +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-09-ctibench-ragas-benchmarks.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-09-fastembed-local-embeddings.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-09-hybrid-typedb-lancedb-architecture.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-09-local-llm-llama-cpp.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-anti-aversion-cleanup.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-causal-graph.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-ctibench-ate-fix.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-format-stability.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-memory-evolution.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-merge-consolidation.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-persistence-semantics.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-15-sqlite-migration.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/2026-04-17-test-suite-audit.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/research/README.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/superpowers/specs/2026-04-15-p1-features-prd.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/docs/tutorials/02-first-cti-report.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/examples/athf_bridge.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/examples/mcp_claude_code.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/examples/quickstart.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/mkdocs.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/scripts/migrate_jsonl_to_sqlite.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/scripts/rebuild_index.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/scripts/record-demo.sh +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/scripts/typedb-setup.sh +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/scripts/zettelforge-rebuild.service +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/scripts/zettelforge-rebuild.timer +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/server.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/skills/claude-code-skill.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/skills/openclaw-skill.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/__main__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/backend_factory.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/detection/__init__.py +1 -1
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/detection/consumers.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/edition.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/integrations/__init__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/mcp/__init__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/mcp/__main__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/__init__.py +1 -1
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/cli.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/parser.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/schemas/NOTICE.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/schemas/__init__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/schemas/sigma-correlation-rules-schema.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/schemas/sigma-detection-rule-schema.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/sigma/schemas/sigma-filters-schema.json +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/__init__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/cccs_metadata.py +2 -2
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/cli.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/parser.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/schemas/CCCS_YARA.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/schemas/CCCS_YARA_values.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/schemas/NOTICE.md +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/schemas/__init__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/src/zettelforge/yara/tags.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/__init__.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/benchmark_scale.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/conftest.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/sigma/cloud_example.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/sigma/correlation_example.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/sigma/process_creation_example.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/sigma/tagged_example.yml +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/yara/malware_hash.yar +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/yara/technique_loader.yar +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/fixtures/yara/webshell.yar +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_basic.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_causal_extraction.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_config.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_conversational_entities.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_core.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_cti_integration.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_detection_explainer.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_detection_rule_entities.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_edition.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_embedding.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_extensions.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_fact_extractor.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_governance.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_graph_retriever.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_human_eval_sampler.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_intent_classifier.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_json_parse.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_langchain_retriever.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_llm_client.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_mcp_server.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_memory_evolver.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_memory_updater.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_performance.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_recall_integration.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_sigma_entities.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_sigma_ingest.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_sigma_parser.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_sqlite_backend.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_sqlite_integration.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_storage_backend.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_telemetry_aggregator.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_telemetry_collector.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_telemetry_dashboard.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_telemetry_integration.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_temporal_graph.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_two_phase_e2e.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_typedb_client.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_yara_entities.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_yara_ingest.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/tests/test_yara_parser.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/web/app.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/web/auth.py +0 -0
- {zettelforge-2.4.1 → zettelforge-2.5.0}/web/mcp_server.py +0 -0
|
@@ -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@
|
|
18
|
-
- uses: actions/setup-python@
|
|
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@
|
|
14
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
15
15
|
|
|
16
16
|
- name: Set up Python
|
|
17
|
-
uses: actions/setup-python@
|
|
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@
|
|
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@
|
|
20
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
21
21
|
|
|
22
22
|
- name: Set up Python
|
|
23
|
-
uses: actions/setup-python@
|
|
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@
|
|
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
|
|
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
|
|
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@
|
|
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,152 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.5.0] - 2026-04-25
|
|
10
|
+
|
|
11
|
+
Compliance-driven minor release. Closes every CRITICAL and HIGH audit
|
|
12
|
+
finding except H-3 (mypy strict) and the ANN slice of H-1, both of
|
|
13
|
+
which need per-module ratchet plans. Also adds two new optional LLM
|
|
14
|
+
backends, a Presidio PII detector, and supply-chain hardening.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **RFC-011 — Local LLM backend selection** (#104). New `local_backend`
|
|
19
|
+
config knob picks between `llama-cpp-python` (GGUF) and
|
|
20
|
+
`onnxruntime-genai` (ONNX) at runtime. Both ship as optional extras
|
|
21
|
+
(`pip install zettelforge[local]` or `[local-onnx]`).
|
|
22
|
+
- **RFC-012 — LiteLLM unified provider** (#108). Routes to 100+
|
|
23
|
+
upstream LLM providers via the LiteLLM SDK. Optional extra
|
|
24
|
+
(`pip install zettelforge[litellm]`); the base package never imports
|
|
25
|
+
it unless the SDK is present.
|
|
26
|
+
- **RFC-013 — Microsoft Presidio PII detection** (#118). Optional PII
|
|
27
|
+
validator with three policies (`log` / `redact` / `block`),
|
|
28
|
+
configurable via `governance.pii.*`. CTI allowlist excludes
|
|
29
|
+
`IP_ADDRESS` / `URL` / `DOMAIN_NAME` from detection so legitimate
|
|
30
|
+
threat-intel indicators flow through unmodified. Soft dependency —
|
|
31
|
+
`pip install zettelforge[pii]` to activate; the base package never
|
|
32
|
+
imports `presidio_analyzer` unless the SDK is present.
|
|
33
|
+
- **GOV-009 Snyk SCA + SAST declared in `controls.yaml`** (#114). The
|
|
34
|
+
spec-drift validator now walks every `.github/workflows/*.yml` so
|
|
35
|
+
controls whose CI step lives outside `ci.yml` (Snyk's separate
|
|
36
|
+
workflow) can be honestly declared.
|
|
37
|
+
- **GOV-006 solo-maintainer compensating controls** (#117). New
|
|
38
|
+
`controls.yaml` entry pins the existing CI gates (lint, tests,
|
|
39
|
+
governance spec-drift) as compensating controls for the GOV-006
|
|
40
|
+
two-person review rule that cannot be physically satisfied with one
|
|
41
|
+
human maintainer. CODEOWNERS updated with explanatory comment.
|
|
42
|
+
- **`SECURITY.md` + CODEOWNERS** added to the repo root for vulnerability
|
|
43
|
+
disclosure and review attribution.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- **All GitHub Actions are now SHA-pinned** (audit H-5 hardening). Every
|
|
48
|
+
`uses: org/repo@vX` reference replaced with `uses: org/repo@<full-sha> # vX.Y.Z`
|
|
49
|
+
to prevent supply-chain attacks via tag rewrites.
|
|
50
|
+
- **Ruff rule set ratcheted to GOV-003 §"Tooling and Automation" minus
|
|
51
|
+
ANN** (#106 + #107 + #109 + #111 + #113). Active `select` list:
|
|
52
|
+
`{E, F, I, W, N, T20, B, UP, SIM, RUF, S}`. Per-line `# noqa: SXXX`
|
|
53
|
+
annotations document each accepted exception (best-effort fallbacks,
|
|
54
|
+
non-crypto RNG, `?`-bound SQL with constant column lists).
|
|
55
|
+
`RUF002`/`RUF003` ignored globally for stylistic en-dash and ×.
|
|
56
|
+
- **CI install-step shell precedence fixed** (#112). The
|
|
57
|
+
`pip install -e ".[dev]" || pip install -e "." && pip install pytest...`
|
|
58
|
+
chain parsed as `(A || B) && C`, so the pytest install ran on
|
|
59
|
+
every success path including when `[dev]` already provided pytest.
|
|
60
|
+
Wrapped the fallback in parentheses.
|
|
61
|
+
- **CONTRIBUTING.md accuracy** (#115). Documents `ruff format`
|
|
62
|
+
(project hasn't used black for a while) and lists what CI actually
|
|
63
|
+
enforces so new contributors have a green-build target.
|
|
64
|
+
|
|
65
|
+
### Compliance audit closure (`tasks/compliance-audit-2026-04-25.md`)
|
|
66
|
+
|
|
67
|
+
| Severity | Finding | Status |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| CRITICAL | C-1 branch protection | CLOSED (with required status checks) |
|
|
70
|
+
| CRITICAL | C-2 fabricated `no_hardcoded_secrets` claim | CLOSED (#100) |
|
|
71
|
+
| 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 |
|
|
72
|
+
| HIGH | H-2 coverage threshold not enforced | CLOSED (#100) |
|
|
73
|
+
| 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 |
|
|
74
|
+
| HIGH | H-5 SCA gate + SHA-pinned actions | CLOSED (#102 + #114 + SHA-pin commit) |
|
|
75
|
+
| MEDIUM | M-1 bare `except:` in production | CLOSED (#100) |
|
|
76
|
+
| MEDIUM | M-3 OCSF `timezone_offset` field | CLOSED (#100) |
|
|
77
|
+
| LOW | L-4 CI install-step shell precedence | CLOSED (#112) |
|
|
78
|
+
|
|
79
|
+
Outstanding: H-3 (mypy --strict in CI; needs per-module ratchet plan
|
|
80
|
+
for 393 errors across 38 files), M-2 (rewrite GOV-016 to match the
|
|
81
|
+
YAML-frontmatter practice already in use), M-4 (lock file), H-1 ANN
|
|
82
|
+
ratchet (121 findings across 38 files).
|
|
83
|
+
|
|
84
|
+
## [2.4.3] - 2026-04-25
|
|
85
|
+
|
|
86
|
+
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.
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- **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.
|
|
91
|
+
- **`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.
|
|
92
|
+
- **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`.
|
|
93
|
+
- **`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).
|
|
94
|
+
- **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.
|
|
95
|
+
|
|
96
|
+
### Operational notes
|
|
97
|
+
|
|
98
|
+
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.
|
|
99
|
+
|
|
100
|
+
## [2.4.2] - 2026-04-24
|
|
101
|
+
|
|
102
|
+
Patch release bundling the RFC-010 enrichment-pipeline hotfix with the
|
|
103
|
+
RFC-009 Phase 0.5 latency-attribution instrumentation. Response to the
|
|
104
|
+
2026-04-24 Vigil telemetry audit.
|
|
105
|
+
|
|
106
|
+
### Fixed
|
|
107
|
+
|
|
108
|
+
- **RFC-010 hotfix — `OllamaProvider` timeout plumbing** (#88). The
|
|
109
|
+
constructor's `**_: Any` absorbed the configured `timeout` kwarg, so
|
|
110
|
+
`ollama.Client(host=...)` was built with no timeout and `remember()`
|
|
111
|
+
could hang up to 66.5s on a slow backend. `timeout` is now a
|
|
112
|
+
first-class parameter (default 60.0s) threaded through to the client.
|
|
113
|
+
- **RFC-010 hotfix — consolidation shutdown race** (#88). A third
|
|
114
|
+
`iterate_notes()` site at `consolidation.py:224` was not covered by
|
|
115
|
+
PR #84's two-site guard. Added a two-layer defense: fast-path
|
|
116
|
+
`_accepting` pre-check plus a narrow `BackendClosedError` catch on
|
|
117
|
+
the iterator itself. Clean skip instead of `consolidation_failed`
|
|
118
|
+
log noise during `atexit`.
|
|
119
|
+
|
|
120
|
+
### Added
|
|
121
|
+
|
|
122
|
+
- **RFC-009 Phase 0.5 — per-phase timers in `remember()`** (#90).
|
|
123
|
+
`memory_manager.remember()` now wraps each direct-store phase
|
|
124
|
+
(`construct`, `write_note`, `lance_index`, `entity_index`,
|
|
125
|
+
`consolidation_observe`, `supersession`, `kg_update`,
|
|
126
|
+
`enrichment_dispatch`) in `time.perf_counter()` and emits the
|
|
127
|
+
breakdown inside the existing `ocsf_api_activity` event as
|
|
128
|
+
`phase_timings_ms`. Pure observability. Enables Vigil-side latency
|
|
129
|
+
attribution without host-side profilers, which do not apply to a
|
|
130
|
+
library-per-turn deployment. `enrichment_dispatch` is intentionally
|
|
131
|
+
skipped in `sync=True` runs so inline LLM work cannot corrupt the
|
|
132
|
+
dispatch bucket.
|
|
133
|
+
- **Phase 0.5 preliminary attribution artifact** (#91) —
|
|
134
|
+
`docs/superpowers/research/2026-04-24-phase-0.5-attribution-prelim.md`.
|
|
135
|
+
Analyses 961 real `remember()` calls from Vigil's v2.4.1 OCSF log
|
|
136
|
+
and finds **98.4% of `remember()` wall-clock is one LanceDB `Update`
|
|
137
|
+
on the `notes_cti` shard**, which has 7,356 uncompacted fragments
|
|
138
|
+
versus 458 on the healthy `notes_general` shard. Reshapes RFC-009's
|
|
139
|
+
Phase 1–6 priority ordering: those phases target the LLM / queue /
|
|
140
|
+
consolidation paths, which are not what drives the 5.7s average.
|
|
141
|
+
To be refined or falsified with `phase_timings_ms` data from this
|
|
142
|
+
release.
|
|
143
|
+
|
|
144
|
+
### Does NOT address
|
|
145
|
+
|
|
146
|
+
- The ~2,329 enrichment-job drops/day are still present. Those are
|
|
147
|
+
caused by HTTP 200 + empty Ollama responses (Ollama returns
|
|
148
|
+
successfully but with no parseable body), not by hangs — RFC-010's
|
|
149
|
+
timeout fix does not touch them. The durable outbox + circuit
|
|
150
|
+
breaker in RFC-009 Phases 1–3 (v2.5.0) is the real fix.
|
|
151
|
+
- LanceDB fragment accumulation on `notes_cti` is identified here but
|
|
152
|
+
not fixed here. RFC-009 is being revised to add periodic compaction
|
|
153
|
+
to Phase 1 scope.
|
|
154
|
+
|
|
9
155
|
## [2.4.1] - 2026-04-24
|
|
10
156
|
|
|
11
157
|
Operational telemetry (RFC-007), TypeDB authentication hardening, and a
|
|
@@ -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: `
|
|
22
|
-
6. Commit with
|
|
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.
|
|
3
|
+
Version: 2.5.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
|
|
@@ -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,25 @@
|
|
|
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
|