zettelforge 2.5.1__tar.gz → 2.6.2__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.6.2/.github/workflows/stale.yml +47 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.gitignore +13 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/CHANGELOG.md +187 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/CONTRIBUTING.md +43 -0
- zettelforge-2.6.2/CONTRIBUTORS.md +17 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/PKG-INFO +9 -2
- {zettelforge-2.5.1 → zettelforge-2.6.2}/README.md +2 -1
- zettelforge-2.6.2/ROADMAP.md +94 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/config.default.yaml +56 -2
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/THREAT_MODEL.md +7 -5
- zettelforge-2.6.2/docs/explanation/llm-budgets-and-timeouts.md +101 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/troubleshoot.md +99 -8
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/upgrade.md +67 -3
- zettelforge-2.6.2/docs/how-to/use-web-interface.md +177 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/index.md +4 -2
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/configuration.md +111 -6
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/module-inventory.md +40 -1
- zettelforge-2.6.2/docs/reference/web-api.md +415 -0
- zettelforge-2.6.2/docs/rfcs/RFC-014-content-limits.md +143 -0
- zettelforge-2.6.2/docs/rfcs/RFC-015-zettelforge-web-gui.md +624 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/mkdocs.yml +1 -0
- zettelforge-2.6.2/pr-body.md +41 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/pyproject.toml +9 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/__init__.py +1 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/config.py +60 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/entity_indexer.py +5 -2
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/fact_extractor.py +3 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/governance_validator.py +17 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/lance_maintenance.py +8 -8
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/ollama_provider.py +1 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/memory_evolver.py +2 -2
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/memory_manager.py +60 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/note_constructor.py +9 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/synthesis_generator.py +5 -1
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_config.py +27 -0
- zettelforge-2.6.2/tests/test_governance.py +125 -0
- zettelforge-2.6.2/tests/test_web_api.py +493 -0
- zettelforge-2.6.2/web/app.py +1005 -0
- zettelforge-2.6.2/web/static/css/design_tokens.css +114 -0
- zettelforge-2.6.2/web/templates/base.html +201 -0
- zettelforge-2.6.2/web/templates/components/remember_panel.html +72 -0
- zettelforge-2.6.2/web/templates/components/result_card.html +98 -0
- zettelforge-2.6.2/web/templates/components/search_bar.html +11 -0
- zettelforge-2.6.2/web/templates/components/synthesis_block.html +58 -0
- zettelforge-2.6.2/web/templates/components/tab_bar.html +42 -0
- zettelforge-2.6.2/web/templates/config_editor.html +799 -0
- zettelforge-2.6.2/web/templates/index.html +279 -0
- zettelforge-2.6.2/web/ui/assets/favicon-16.png +0 -0
- zettelforge-2.6.2/web/ui/assets/favicon-32.png +0 -0
- zettelforge-2.6.2/web/ui/assets/favicon-512.png +0 -0
- zettelforge-2.6.2/web/ui/assets/favicon-apple-touch.png +0 -0
- zettelforge-2.6.2/web/ui/assets/logo.svg +42 -0
- zettelforge-2.6.2/web/ui/assets/threatrecall-lockup.svg +39 -0
- zettelforge-2.6.2/web/ui/assets/zettelforge_architecture.svg +104 -0
- zettelforge-2.6.2/web/ui/colors_and_type.css +286 -0
- zettelforge-2.6.2/web/ui/favicon.svg +33 -0
- zettelforge-2.6.2/web/ui/fonts/Neuropol.otf +0 -0
- zettelforge-2.6.2/web/ui/index.html +55 -0
- zettelforge-2.6.2/web/ui/js/app.js +144 -0
- zettelforge-2.6.2/web/ui/js/components/header.js +95 -0
- zettelforge-2.6.2/web/ui/js/components/result-card.js +69 -0
- zettelforge-2.6.2/web/ui/js/components/sidebar.js +57 -0
- zettelforge-2.6.2/web/ui/js/components/spinner.js +8 -0
- zettelforge-2.6.2/web/ui/js/components/tabs.js +17 -0
- zettelforge-2.6.2/web/ui/js/components/toast.js +35 -0
- zettelforge-2.6.2/web/ui/js/lib/api.js +83 -0
- zettelforge-2.6.2/web/ui/js/lib/state.js +50 -0
- zettelforge-2.6.2/web/ui/js/views/configuration.js +784 -0
- zettelforge-2.6.2/web/ui/js/views/dashboard.js +251 -0
- zettelforge-2.6.2/web/ui/js/views/entities.js +415 -0
- zettelforge-2.6.2/web/ui/js/views/history.js +296 -0
- zettelforge-2.6.2/web/ui/js/views/ingest.js +425 -0
- zettelforge-2.6.2/web/ui/js/views/knowledge-graph.js +606 -0
- zettelforge-2.6.2/web/ui/js/views/logs.js +256 -0
- zettelforge-2.6.2/web/ui/js/views/search.js +343 -0
- zettelforge-2.5.1/docs/superpowers/research/2026-04-09-ctibench-ragas-benchmarks.md +0 -31
- zettelforge-2.5.1/docs/superpowers/research/2026-04-09-fastembed-local-embeddings.md +0 -460
- zettelforge-2.5.1/docs/superpowers/research/2026-04-09-hybrid-typedb-lancedb-architecture.md +0 -855
- zettelforge-2.5.1/docs/superpowers/research/2026-04-09-local-llm-llama-cpp.md +0 -17
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-anti-aversion-cleanup.md +0 -763
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-causal-graph.md +0 -409
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-ctibench-ate-fix.md +0 -211
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-format-stability.md +0 -1029
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-memory-evolution.md +0 -428
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-merge-consolidation.md +0 -372
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-persistence-semantics.md +0 -422
- zettelforge-2.5.1/docs/superpowers/research/2026-04-15-sqlite-migration.md +0 -636
- zettelforge-2.5.1/docs/superpowers/research/2026-04-17-test-suite-audit.md +0 -178
- zettelforge-2.5.1/docs/superpowers/research/2026-04-24-phase-0.5-attribution-prelim.md +0 -123
- zettelforge-2.5.1/docs/superpowers/research/2026-04-25-graph-retriever-silence.md +0 -117
- zettelforge-2.5.1/docs/superpowers/research/2026-04-25-phase-0.5-attribution.md +0 -230
- zettelforge-2.5.1/docs/superpowers/research/README.md +0 -40
- zettelforge-2.5.1/docs/superpowers/specs/2026-04-15-p1-features-prd.md +0 -990
- zettelforge-2.5.1/tests/test_governance.py +0 -32
- zettelforge-2.5.1/web/app.py +0 -530
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/CODEOWNERS +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/SECURITY.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/dependabot.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/pull_request_template.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/workflows/ci.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/workflows/docs.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/workflows/publish.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/.github/workflows/snyk-security.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/ARCHITECTURE.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/CODEOWNERS +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/CODE_OF_CONDUCT.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/Dockerfile +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/GOVERNANCE.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/LICENSE +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/MANIFEST.in +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/SECURITY.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/BENCHMARK_REPORT.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/LOCOMO_BENCHMARK_COMPARISON.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/auto_ralph.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/benchmark_harness.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/cti_benchmark_v2.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/cti_retrieval_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/cti_retrieval_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/cti_v2_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/ctibench_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/ctibench_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/dataset.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/enterprise-attack.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/evolve_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/evolve_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/graph_test.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/locomo_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/locomo_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/locomo_results_v1.3.0_baseline.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/memoryagentbench.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/memoryagentbench_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/mempalace_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/mempalace_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/naive_memory.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/opencti_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/ragas_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/ragas_cti_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/ragas_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/results/benchmark_report.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/results/ralph_optimization_log.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/scale_benchmark.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/benchmarks/scale_results.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/config.example.yaml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docker/docker-compose.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/.well-known/security.txt +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/CNAME +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/architecture-diagram.mmd +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/archive/PACKAGE_SUMMARY.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/archive/README.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/archive/SKILL.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/ZettelForge_Architecture.mmd +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/architecture-overview.mmd +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/architecture-read-path.mmd +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/architecture-write-path.mmd +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/cf-analytics.js +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/demo.gif +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon-16.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon-32.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon-512.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon-64.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon-apple-touch.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon-old.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/favicon.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/logo.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/social-preview.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/threatrecall-lockup-monogram.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/threatrecall-lockup.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/threatrecall-logo-flat.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/threatrecall-logo-philosophy.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/threatrecall-logo.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/threatrecall-mark.png +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/zettelforge_architecture-light.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/assets/zettelforge_architecture.svg +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/brand/brandIdentity.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/brand/colors_and_type.css +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/explanation/architecture.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/explanation/epistemic-tiers.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/explanation/stix-in-zettelforge.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/explanation/two-phase-pipeline.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/explanation/zettelkasten-philosophy.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/configure-lancedb.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/configure-opencti.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/configure-pii.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/configure-typedb.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/ingest-news-report.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/integrate-llm-agent.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/migrate-jsonl-to-sqlite.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/query-apt-tools.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/reproduce-benchmarks.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/resolve-aliases.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/run-temporal-query.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/how-to/store-threat-actor.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/human-evaluation-rubric.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/llms.txt +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/narrative/2026-04-16-the-memory-problem.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/overrides/main.html +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/architecture-deep-dive.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/governance-controls.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/memory-manager-api.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/retrieval-policies.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/reference/stix-schema.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-001-conversational-entity-extractor.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-002-universal-llm-provider.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-003-adversarial-review.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-003-read-path-depth-routing.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-007-operational-telemetry.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-009-enrichment-pipeline-v2.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-010-enrichment-hotfix.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-011-local-llm-backend-config.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-012-litellm-unified-provider.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/rfcs/RFC-013-presidio-pii-detection.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/stylesheets/brand-tokens.css +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/stylesheets/extra.css +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/stylesheets/fonts/Neuropol.otf +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/tutorials/01-quickstart.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/docs/tutorials/02-first-cti-report.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/examples/athf_bridge.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/examples/mcp_claude_code.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/examples/quickstart.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/governance/controls.yaml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/scripts/migrate_jsonl_to_sqlite.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/scripts/rebuild_index.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/scripts/record-demo.sh +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/scripts/typedb-setup.sh +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/scripts/zettelforge-rebuild.service +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/scripts/zettelforge-rebuild.timer +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/server.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/skills/claude-code-skill.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/skills/openclaw-skill.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/__main__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/alias_resolver.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/backend_factory.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/blended_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/cache.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/consolidation.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/demo.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/detection/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/detection/base.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/detection/consumers.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/detection/explainer.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/edition.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/extensions.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/graph_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/integrations/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/integrations/langchain_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/intent_classifier.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/json_parse.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/knowledge_graph.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_client.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/base.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/litellm_provider.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/local_provider.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/mock_provider.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/llm_providers/registry.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/log.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/mcp/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/mcp/__main__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/mcp/server.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/memory_store.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/memory_updater.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/note_schema.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/observability.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/ocsf.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/ontology.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/pii_validator.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/retry.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/scripts/compact_lance.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/scripts/human_eval_sampler.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/scripts/telemetry_aggregator.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/scripts/telemetry_dashboard.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/cli.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/entities.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/ingest.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/parser.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/schemas/NOTICE.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/schemas/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/schemas/sigma-correlation-rules-schema.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/schemas/sigma-detection-rule-schema.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/schemas/sigma-filters-schema.json +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sigma/tags.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/sqlite_backend.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/storage_backend.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/synthesis_validator.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/telemetry.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/vector_memory.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/vector_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/cccs_metadata.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/cli.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/entities.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/ingest.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/parser.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/schemas/CCCS_YARA.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/schemas/CCCS_YARA_values.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/schemas/NOTICE.md +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/schemas/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/src/zettelforge/yara/tags.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/__init__.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/benchmark_scale.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/conftest.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/sigma/cloud_example.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/sigma/correlation_example.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/sigma/process_creation_example.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/sigma/tagged_example.yml +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/yara/malware_hash.yar +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/yara/technique_loader.yar +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/fixtures/yara/webshell.yar +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_basic.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_blended_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_causal_extraction.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_consolidation.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_conversational_entities.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_core.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_cti_integration.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_detection_explainer.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_detection_rule_entities.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_edition.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_embedding.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_entity_indexer_races.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_extensions.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_fact_extractor.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_governance_spec_drift.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_graph_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_human_eval_sampler.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_intent_classifier.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_json_parse.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_kg_edge_schema.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_lance_maintenance.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_langchain_retriever.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_llm_client.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_llm_providers.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_logging_compliance.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_mcp_server.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_memory_evolver.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_memory_updater.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_performance.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_pii_validator.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_recall_integration.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_sigma_entities.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_sigma_ingest.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_sigma_parser.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_sqlite_backend.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_sqlite_integration.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_storage_backend.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_telemetry_aggregator.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_telemetry_collector.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_telemetry_dashboard.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_telemetry_integration.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_temporal_graph.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_two_phase_e2e.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_typedb_client.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_yara_entities.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_yara_ingest.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/tests/test_yara_parser.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/web/auth.py +0 -0
- {zettelforge-2.5.1 → zettelforge-2.6.2}/web/mcp_server.py +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Stale issue and PR management
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 9 * * 1" # Every Monday at 09:00 UTC
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
issues: write
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
stale:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/stale@v9
|
|
16
|
+
with:
|
|
17
|
+
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
18
|
+
|
|
19
|
+
# Issues
|
|
20
|
+
stale-issue-message: >
|
|
21
|
+
This issue has been inactive for 60 days. It will be closed
|
|
22
|
+
in 14 days unless there is new activity. If this is still
|
|
23
|
+
relevant, please comment to keep it open.
|
|
24
|
+
close-issue-message: >
|
|
25
|
+
This issue has been automatically closed after 14 days of
|
|
26
|
+
inactivity. It can be reopened at any time.
|
|
27
|
+
days-before-issue-stale: 60
|
|
28
|
+
days-before-issue-close: 14
|
|
29
|
+
stale-issue-label: stale
|
|
30
|
+
exempt-issue-labels: "p0,planned,help wanted,good first issue"
|
|
31
|
+
|
|
32
|
+
# PRs
|
|
33
|
+
stale-pr-message: >
|
|
34
|
+
This pull request has been inactive for 60 days. It will be
|
|
35
|
+
closed in 14 days unless there is new activity.
|
|
36
|
+
close-pr-message: >
|
|
37
|
+
This pull request has been automatically closed after 14 days
|
|
38
|
+
of inactivity.
|
|
39
|
+
days-before-pr-stale: 60
|
|
40
|
+
days-before-pr-close: 14
|
|
41
|
+
stale-pr-label: stale
|
|
42
|
+
exempt-pr-labels: "draft,work-in-progress"
|
|
43
|
+
|
|
44
|
+
# General
|
|
45
|
+
operations-per-run: 100
|
|
46
|
+
remove-stale-when-updated: true
|
|
47
|
+
delete-branch: false
|
|
@@ -12,6 +12,17 @@ tasks/
|
|
|
12
12
|
docs/.ralph/
|
|
13
13
|
agentsync.md
|
|
14
14
|
|
|
15
|
+
# Internal research/specs/plans — workspace scratch that contains
|
|
16
|
+
# unredacted incident detail, customer references, and intermediate
|
|
17
|
+
# reasoning. Kept on disk for the maintainer; not published.
|
|
18
|
+
docs/superpowers/
|
|
19
|
+
|
|
20
|
+
# Claude Code session artifacts — agent worktrees, transcripts, and
|
|
21
|
+
# scratch state created by the maintainer's local tooling. Belt-and-
|
|
22
|
+
# suspenders: these were never tracked, but listing them prevents an
|
|
23
|
+
# accidental `git add -A` from sweeping them in.
|
|
24
|
+
.claude/
|
|
25
|
+
|
|
15
26
|
# MkDocs build output (regenerated from docs/)
|
|
16
27
|
site/
|
|
17
28
|
|
|
@@ -28,6 +39,8 @@ downloads/
|
|
|
28
39
|
eggs/
|
|
29
40
|
.eggs/
|
|
30
41
|
lib/
|
|
42
|
+
!web/ui/js/lib/
|
|
43
|
+
!web/ui/js/lib/*.js
|
|
31
44
|
lib64/
|
|
32
45
|
parts/
|
|
33
46
|
sdist/
|
|
@@ -6,6 +6,193 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.6.2] - 2026-04-27
|
|
10
|
+
|
|
11
|
+
UI/UX release. Fixes the `/config` page so the Apply button actually works
|
|
12
|
+
and surfaces enum-style settings as dropdowns instead of free-text inputs.
|
|
13
|
+
No data migration. No config changes. No API contract changes.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **`/config` "Save Changes" button is no longer dead.** The Quick Settings
|
|
18
|
+
panel called `saveConfigForm()` and `reloadConfig()` — neither function
|
|
19
|
+
was defined anywhere, so the button silently no-op'd and the panel
|
|
20
|
+
rendered "Loading schema..." forever. Replaced with a real form-based
|
|
21
|
+
editor whose Apply button PUTs a nested payload to `/api/config` and
|
|
22
|
+
reloads from server on success.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Form-based config editor with dropdowns.** `/config` now renders a
|
|
27
|
+
grouped settings form alongside the YAML editor. Known enum fields
|
|
28
|
+
(`backend`, `embedding.provider`, `llm.provider`, `llm.local_backend`,
|
|
29
|
+
`logging.level`, `synthesis.default_format`, `governance.pii.action`)
|
|
30
|
+
render as `<select>` controls instead of free-text inputs. Restart-
|
|
31
|
+
required leaves get a "restart required" badge sourced from the same
|
|
32
|
+
set the server uses, so the UI warning is never out of sync with the
|
|
33
|
+
server's classification.
|
|
34
|
+
- **Pending-changes counter and Revert button.** The form tracks dirty
|
|
35
|
+
fields by dotted path, builds a single nested payload on Apply, and
|
|
36
|
+
shows `N pending change(s) (M need restart)` next to the buttons.
|
|
37
|
+
- **YAML editor accepts both YAML and JSON** (was JSON-only despite the
|
|
38
|
+
label) and skips redacted `***` secrets so they aren't PUT back as
|
|
39
|
+
literal strings.
|
|
40
|
+
|
|
41
|
+
### Tests
|
|
42
|
+
|
|
43
|
+
- 4 new tests in `tests/test_web_api.py`: dropdown enum round-trip for
|
|
44
|
+
`logging.level` (restart-required) and `synthesis.default_format` (live);
|
|
45
|
+
multi-section nested payload from a single Apply; and a regression guard
|
|
46
|
+
on the `/config` HTML structure (form tab, dropdown enum declarations,
|
|
47
|
+
restart-leaf flags, and proof the dead `saveConfigForm`/`reloadConfig`
|
|
48
|
+
handlers are gone). 28 passed, 2 skipped (was 24 + 2).
|
|
49
|
+
|
|
50
|
+
## [2.6.1] - 2026-04-25
|
|
51
|
+
|
|
52
|
+
Hotfix release. Resolves three blockers found in code review of the
|
|
53
|
+
RFC-015 web GUI shipped in v2.6.0. No data migration. No config changes.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- **`/config` HTML page now renders.** `_to_dict` was defined as a closure
|
|
58
|
+
inside `get_config_endpoint`, so every render of `/config` raised
|
|
59
|
+
`NameError`, was silently swallowed by a bare `except`, and left the
|
|
60
|
+
YAML body blank on initial server-side render. Promoted to a module-level
|
|
61
|
+
`_config_to_dict` helper used by both routes. (PR #131)
|
|
62
|
+
- **`PUT /api/config` correctly reports nested restart-required fields.**
|
|
63
|
+
The check compared top-level payload keys against a set of dotted-path
|
|
64
|
+
fields, so payloads like `{"embedding": {"provider": "x"}}` were
|
|
65
|
+
reported as `applied: ["embedding"]`, `pending_restart: []`, telling
|
|
66
|
+
operators a restart-required change had taken effect when it had not.
|
|
67
|
+
Added `_flatten_keys` to walk nested payloads to dotted leaf paths;
|
|
68
|
+
`applied` and `pending_restart` now contain accurate dotted paths.
|
|
69
|
+
(PR #131)
|
|
70
|
+
- **`/config` HTML route is now auth-gated.** `/api/config` was protected,
|
|
71
|
+
but the HTML shell (and once the `_to_dict` bug was fixed, its
|
|
72
|
+
server-rendered YAML body) was reachable without an API key. Added
|
|
73
|
+
`Depends(require_api_guard)` and made the YAML body redact secrets
|
|
74
|
+
before serialization. (PR #131)
|
|
75
|
+
|
|
76
|
+
### Tests
|
|
77
|
+
|
|
78
|
+
- Added four regression tests in `tests/test_web_api.py` covering all
|
|
79
|
+
three fixes. 24 passed, 2 skipped (was 20 + 2).
|
|
80
|
+
|
|
81
|
+
## [2.6.0] - 2026-04-25
|
|
82
|
+
|
|
83
|
+
Feature release. Adds configurable content-size limits for DoS mitigation
|
|
84
|
+
(RFC-014) and moves per-call-site LLM token budgets out of hardcoded
|
|
85
|
+
literals into `LLMConfig`, making them overridable at deploy time.
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **Configurable content size limits** (`GovernanceConfig.limits.max_content_length`,
|
|
90
|
+
default 50 MB). `remember()` calls with content exceeding the limit are
|
|
91
|
+
rejected with a clear error message. Set to `0` to disable the check.
|
|
92
|
+
Environment override: `ZETTELFORGE_LIMITS_MAX_CONTENT_LENGTH`.
|
|
93
|
+
(RFC-014, PR #123)
|
|
94
|
+
- **Per-call-site `max_tokens` budgets configurable via `LLMConfig`**.
|
|
95
|
+
Five new fields: `max_tokens_causal` (8000), `max_tokens_synthesis` (2500),
|
|
96
|
+
`max_tokens_fact` (2500), `max_tokens_ner` (2500), `max_tokens_evolution` (2500).
|
|
97
|
+
Defaults match v2.5.2 values. No behavioral change for existing configs.
|
|
98
|
+
(PR #126, issue #125)
|
|
99
|
+
|
|
100
|
+
### Changed
|
|
101
|
+
|
|
102
|
+
- **Docs: config reconciliation for v2.5.2** — `config.default.yaml` gained
|
|
103
|
+
the `lance:` section (RFC-009 Phase 1.5), `docs/reference/configuration.md`
|
|
104
|
+
now covers all v2.5.2 knobs (`lance`, `pii`, per-call-site budgets), and
|
|
105
|
+
`docs/explanation/llm-budgets-and-timeouts.md` explains the reasoning-model
|
|
106
|
+
token-budget tradeoffs. (PR #126)
|
|
107
|
+
- **`_apply_yaml()` now handles `lance:` section** — previously the
|
|
108
|
+
`lance.cleanup_interval_minutes` and `lance.cleanup_older_than_seconds` YAML
|
|
109
|
+
knobs were silently ignored (regression from RFC-009 Phase 1.5 landing in
|
|
110
|
+
v2.4.x without the `_apply_yaml` branch). (PR #126, code review finding)
|
|
111
|
+
|
|
112
|
+
### Internal
|
|
113
|
+
|
|
114
|
+
- **Removed `docs/superpowers/` from version control**. The directory holds
|
|
115
|
+
workspace scratch — internal research and notes with unredacted incident
|
|
116
|
+
detail. 18 files (7319 lines) untracked. No published content lost.
|
|
117
|
+
(PR #128)
|
|
118
|
+
|
|
119
|
+
## [2.5.2] - 2026-04-25
|
|
120
|
+
|
|
121
|
+
Hotfix release. Restores end-to-end functionality of synthesis, causal
|
|
122
|
+
triple extraction, fact extraction, LLM NER, and neighbor evolution
|
|
123
|
+
under any reasoning-style LLM (qwen3.5+, qwen3.6, nemotron-3, etc.).
|
|
124
|
+
|
|
125
|
+
### Fixed
|
|
126
|
+
|
|
127
|
+
- **Reasoning-model token starvation across every LLM call site**.
|
|
128
|
+
Reasoning models emit hidden `<think>...</think>` tokens that count
|
|
129
|
+
against `num_predict` but never appear in the final `response` field
|
|
130
|
+
Ollama returns. Pre-2.5.2 token caps (`max_tokens=300`/`400`/`800`/
|
|
131
|
+
`1024`) were exhausted entirely by the thinking phase on these
|
|
132
|
+
models, leaving the JSON answer empty. Symptoms: synthesis fell back
|
|
133
|
+
to `"No specific answer found for: …"` on every query; causal triple
|
|
134
|
+
extraction persisted **0 edges** despite rich CTI text; LLM NER
|
|
135
|
+
silently no-opped; neighbor evolution `parse_failed{schema=...,
|
|
136
|
+
raw=""}` warnings flooded the log.
|
|
137
|
+
|
|
138
|
+
Bumped every `generate(..., max_tokens=...)` call site to give
|
|
139
|
+
reasoning models room to think *and* emit a final answer. Affected
|
|
140
|
+
files:
|
|
141
|
+
|
|
142
|
+
| File | Old cap | New cap |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `note_constructor.py` (causal triples) | 300 | **8000** |
|
|
145
|
+
| `synthesis_generator.py` | 800 | 2500 |
|
|
146
|
+
| `fact_extractor.py` | 400 | 2500 |
|
|
147
|
+
| `entity_indexer.py` (NER) | 300 | 2500 |
|
|
148
|
+
| `memory_evolver.py` (2 sites) | 1024 | 2500 |
|
|
149
|
+
|
|
150
|
+
Causal extraction needs the largest budget because the prompt asks
|
|
151
|
+
the model to enumerate *every* causal relation in a passage; this
|
|
152
|
+
triggers the longest reasoning chains anywhere in the system.
|
|
153
|
+
Empirical against `qwen3.5:9b`: at 4000 tokens the call was
|
|
154
|
+
*stochastically* sufficient (eval_count varied 2.8k–4k+, ~70%
|
|
155
|
+
success), so 8000 is the conservative cap that keeps the success
|
|
156
|
+
rate above 95% on the same model. Other call sites converge with
|
|
157
|
+
less reasoning overhead so 2500 suffices.
|
|
158
|
+
|
|
159
|
+
- **LLM client timeout bumped 60s → 180s**. `LLMConfig.timeout` and
|
|
160
|
+
`OllamaProvider` constructor default were both 60 seconds — well
|
|
161
|
+
below the 60–120s wall-clock time of a 4000–8000 token reasoning
|
|
162
|
+
generation on a 9B-Q4_K_M model. `ReadTimeout` was firing during
|
|
163
|
+
causal extraction even when the model would have returned valid
|
|
164
|
+
JSON given another 30 seconds. Bumped both defaults plus
|
|
165
|
+
`config.default.yaml` to 180s.
|
|
166
|
+
|
|
167
|
+
Verified end-to-end on `qwen3.5:9b`:
|
|
168
|
+
- Synthesis: query "What CVE does DROPBEAR exploit?" returns
|
|
169
|
+
`"CVE-2024-3094"` with 1 source citation (was returning
|
|
170
|
+
`"No specific answer found for: …"` on every call pre-2.5.2).
|
|
171
|
+
- Causal extraction: corpus seeded with APT28/DROPBEAR/CVE-2024-3094
|
|
172
|
+
text yields a 4-triple JSON array in 137s wall time:
|
|
173
|
+
`APT28 → targets → manufacturing sector`,
|
|
174
|
+
`APT28 → uses → DROPBEAR`,
|
|
175
|
+
`DROPBEAR → exploits → CVE-2024-3094`,
|
|
176
|
+
`APT28 → attributed_to → Russian GRU Unit 26165`.
|
|
177
|
+
|
|
178
|
+
### Operational note
|
|
179
|
+
|
|
180
|
+
Slow models. With 8000 tokens of reasoning budget, single causal
|
|
181
|
+
extraction calls now take 60–140s on a 9B model. `remember(sync=True)`
|
|
182
|
+
in this configuration will block 1–3 minutes per note. The default
|
|
183
|
+
async path (background enrichment queue) is the preferred mode.
|
|
184
|
+
Operators on faster hardware or smaller models can lower the caps via
|
|
185
|
+
config/env if needed, but the v2.5.2 defaults trade latency for
|
|
186
|
+
end-to-end correctness on the reference model.
|
|
187
|
+
|
|
188
|
+
### Notes
|
|
189
|
+
|
|
190
|
+
This explains the `evolution_parse_failed` and `causal_triples
|
|
191
|
+
parse_failed` cascades documented in the v2.4.x Vigil incident. The
|
|
192
|
+
v2.4.2 PR #95 Tier 1/2 LLM observability surfaced the empty responses
|
|
193
|
+
but the root-cause attribution to token-cap-vs-thinking-budget waited
|
|
194
|
+
until the v2.5.1 perf-bench run made the failure reproducible end-to-end.
|
|
195
|
+
|
|
9
196
|
## [2.5.1] - 2026-04-25
|
|
10
197
|
|
|
11
198
|
Hotfix release. Surfaced during the v2.5.0 perf benchmark run.
|
|
@@ -37,6 +37,49 @@ If your contribution needs TypeDB or OpenCTI, open an issue to discuss.
|
|
|
37
37
|
We keep the extension boundary clear so contributors know their work
|
|
38
38
|
will always remain open source.
|
|
39
39
|
|
|
40
|
+
### For major features: Start with an RFC
|
|
41
|
+
|
|
42
|
+
If you're proposing a significant new feature (new subsystem, new backend,
|
|
43
|
+
breaking API change), open an RFC before writing code. RFCs live in
|
|
44
|
+
`docs/rfcs/` and follow the template from the existing RFCs in that
|
|
45
|
+
directory. Open a Discussion first to socialize the idea, then file a
|
|
46
|
+
draft RFC as a PR. This prevents wasted effort on work that won't be
|
|
47
|
+
accepted.
|
|
48
|
+
|
|
49
|
+
See [ROADMAP.md](ROADMAP.md) for the current priorities and what's
|
|
50
|
+
planned for upcoming releases.
|
|
51
|
+
|
|
52
|
+
### Good first issues
|
|
53
|
+
|
|
54
|
+
Issues tagged [good first issue](https://github.com/rolandpg/zettelforge/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
|
55
|
+
have structured acceptance criteria in the issue body. Check the issue
|
|
56
|
+
for: which files to edit, test expectations, and example input/output.
|
|
57
|
+
If an issue is unclear, ask in the issue comments.
|
|
58
|
+
|
|
59
|
+
## Issue triage
|
|
60
|
+
|
|
61
|
+
This project is maintained by a solo developer (per GOV-006). Here is
|
|
62
|
+
what you can expect:
|
|
63
|
+
|
|
64
|
+
- **New issues**: triaged within 7 days. You will get a response (even
|
|
65
|
+
if it's "not planned, closing").
|
|
66
|
+
- **Bug reports**: severity assessed within 7 days. P0 (crash, data
|
|
67
|
+
loss, security) gets a same-day response.
|
|
68
|
+
- **Feature requests**: tagged with `enhancement` on creation. The
|
|
69
|
+
maintainer will add `planned`, `deferred`, or `won't fix` within 7
|
|
70
|
+
days.
|
|
71
|
+
- **PR reviews**: first review within 14 days of submission. Smaller
|
|
72
|
+
PRs get reviewed faster.
|
|
73
|
+
- **Stale issues**: issues with no activity for 60 days are tagged
|
|
74
|
+
`stale` and closed after 14 more days without response. This keeps
|
|
75
|
+
the tracker manageable for a solo maintainer.
|
|
76
|
+
|
|
77
|
+
## Contributor recognition
|
|
78
|
+
|
|
79
|
+
Every contributor is listed in [CONTRIBUTORS.md](CONTRIBUTORS.md),
|
|
80
|
+
regardless of contribution size. If you submit a PR that gets merged,
|
|
81
|
+
you will be added. If your name is missing, open a PR.
|
|
82
|
+
|
|
40
83
|
## Code Style
|
|
41
84
|
|
|
42
85
|
- Follow PEP 8
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Contributors
|
|
2
|
+
|
|
3
|
+
Thank you to everyone who has contributed to ZettelForge.
|
|
4
|
+
|
|
5
|
+
## Maintainers
|
|
6
|
+
|
|
7
|
+
- **Patrick G. Roland II** — creator and lead maintainer
|
|
8
|
+
|
|
9
|
+
## Contributors
|
|
10
|
+
|
|
11
|
+
This file tracks individuals who have contributed code, documentation, design, or other improvements. The maintainer updates it with each release.
|
|
12
|
+
|
|
13
|
+
If you have contributed and your name is missing, please open a PR or issue.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
*This project uses a "thank you, next" acknowledgment model. All contributors are listed regardless of contribution size. A typo fix counts.*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zettelforge
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.2
|
|
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
|
|
@@ -36,12 +36,16 @@ Requires-Dist: requests>=2.31.0
|
|
|
36
36
|
Requires-Dist: structlog>=24.0.0
|
|
37
37
|
Requires-Dist: tantivy>=0.11.0
|
|
38
38
|
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: fastapi>=0.100.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: jinja2>=3.0.0; extra == 'dev'
|
|
39
41
|
Requires-Dist: langchain-core>=0.2.0; extra == 'dev'
|
|
40
42
|
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: psutil>=5.9.0; extra == 'dev'
|
|
41
44
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
42
45
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
43
46
|
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
44
47
|
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
48
|
+
Requires-Dist: uvicorn>=0.20.0; extra == 'dev'
|
|
45
49
|
Provides-Extra: extensions
|
|
46
50
|
Requires-Dist: zettelforge-enterprise>=2.1.0; extra == 'extensions'
|
|
47
51
|
Provides-Extra: langchain
|
|
@@ -61,6 +65,8 @@ Requires-Dist: presidio-anonymizer>=2.2.0; extra == 'pii'
|
|
|
61
65
|
Requires-Dist: spacy>=3.5.0; extra == 'pii'
|
|
62
66
|
Provides-Extra: web
|
|
63
67
|
Requires-Dist: fastapi>=0.100.0; extra == 'web'
|
|
68
|
+
Requires-Dist: jinja2>=3.0.0; extra == 'web'
|
|
69
|
+
Requires-Dist: psutil>=5.9.0; extra == 'web'
|
|
64
70
|
Requires-Dist: uvicorn>=0.20.0; extra == 'web'
|
|
65
71
|
Description-Content-Type: text/markdown
|
|
66
72
|
|
|
@@ -79,8 +85,9 @@ It extracts CVEs, threat actors, IOCs, and ATT&CK techniques from analyst notes
|
|
|
79
85
|
[](https://www.python.org/downloads/)
|
|
80
86
|
[](https://opensource.org/licenses/MIT)
|
|
81
87
|
[](https://github.com/rolandpg/zettelforge/actions)
|
|
88
|
+
[](https://github.com/rolandpg/zettelforge/issues)
|
|
82
89
|
|
|
83
|
-
**[⭐ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted beta](https://threatrecall.ai)**
|
|
90
|
+
**[⭐ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted beta](https://threatrecall.ai) · [🗺️ Roadmap](ROADMAP.md)**
|
|
84
91
|
|
|
85
92
|
<p align="center">
|
|
86
93
|
<a href="https://www.buymeacoffee.com/xypher22pr0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me a Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
@@ -13,8 +13,9 @@ It extracts CVEs, threat actors, IOCs, and ATT&CK techniques from analyst notes
|
|
|
13
13
|
[](https://www.python.org/downloads/)
|
|
14
14
|
[](https://opensource.org/licenses/MIT)
|
|
15
15
|
[](https://github.com/rolandpg/zettelforge/actions)
|
|
16
|
+
[](https://github.com/rolandpg/zettelforge/issues)
|
|
16
17
|
|
|
17
|
-
**[⭐ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted beta](https://threatrecall.ai)**
|
|
18
|
+
**[⭐ Star](https://github.com/rolandpg/zettelforge) · [📦 `pip install zettelforge`](https://pypi.org/project/zettelforge/) · [📖 Docs](https://docs.threatrecall.ai/) · [🧪 Hosted beta](https://threatrecall.ai) · [🗺️ Roadmap](ROADMAP.md)**
|
|
18
19
|
|
|
19
20
|
<p align="center">
|
|
20
21
|
<a href="https://www.buymeacoffee.com/xypher22pr0" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me a Coffee" style="height: 60px !important;width: 217px !important;" ></a>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# ZettelForge Roadmap
|
|
2
|
+
|
|
3
|
+
Last updated: 2026-04-25
|
|
4
|
+
|
|
5
|
+
This document communicates what the maintainer is building, what is on hold, and what is out of scope. It is updated when priorities shift.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Current release: v2.6.1
|
|
10
|
+
|
|
11
|
+
Shipped: 2026-04-25. See `CHANGELOG.md` for details.
|
|
12
|
+
|
|
13
|
+
The v2.6 series (RFC-013 through RFC-015) delivered PII detection (Presidio), configurable content size limits, and the Web Management Interface. The v2.5 series (RFC-009 through RFC-012) delivered the enrichment pipeline v2, local LLM backends, and unified provider config.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## v2.7.0 targets (next release)
|
|
18
|
+
|
|
19
|
+
Target: 2026-05-09. Scope is frozen at the items below. Everything else defers to v2.8.0 unless marked **P0**.
|
|
20
|
+
|
|
21
|
+
### Must ship (P0)
|
|
22
|
+
|
|
23
|
+
- [ ] **Issue #125: Harden reasoning-model LLM budget plumbing.** Regression tests for `max_tokens` at each call site, config-overridable budgets, `thinking` tag stripping in `json_parse.py`, and a `reasoning_model: bool` auto-scaling flag. Post-#124 follow-up. (Est: 2-3 days)
|
|
24
|
+
- [ ] **Issue #73: Tighten CCCS metadata regexes (SEC-6 / SEC-7).** Low hanging security hardening. (Est: 0.5 day)
|
|
25
|
+
- [ ] **Issue #72: MemoryManager.remember(sync=True) dominates bulk ingest.** The YARA p95 plyara tail needs a timeout or chunked processing path. (Est: 1 day)
|
|
26
|
+
|
|
27
|
+
### Nice to have (P1)
|
|
28
|
+
|
|
29
|
+
- [ ] **Issue #71: Add typed DetectionMeta extension to MemoryNote.Metadata.** Paves the way for richer entity metadata downstream. (Est: 0.5 day)
|
|
30
|
+
- [ ] **Issue #51: Ratchet governance coverage threshold from 67% toward 80%.** Incremental. (Est: 1 day)
|
|
31
|
+
|
|
32
|
+
### Community items (open for contribution)
|
|
33
|
+
|
|
34
|
+
See the [good first issue](https://github.com/rolandpg/zettelforge/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label. These are pre-scoped with acceptance criteria:
|
|
35
|
+
|
|
36
|
+
- #47 — IPv6 address extraction
|
|
37
|
+
- #46 — YARA rule reference extraction
|
|
38
|
+
- #45 — Sigma rule ID extraction
|
|
39
|
+
- #39 — Threat actor alias mappings for Chinese APT groups
|
|
40
|
+
- #36 — Architecture decision records (ADRs)
|
|
41
|
+
- #44 — Example: MISP JSON feed ingestion
|
|
42
|
+
- #43 — Example: Slack bot for CTI queries
|
|
43
|
+
- #41 — Example: Jupyter notebook CTI analysis workflow
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Next release (v2.7.1+)
|
|
48
|
+
|
|
49
|
+
Target: approximately 2026-05-23. Provisional scope; will be finalized after v2.7.0 ships.
|
|
50
|
+
|
|
51
|
+
- [ ] **CrewAI tool wrapper** (#40). Integration path for CrewAI agents to use ZettelForge as a memory backend.
|
|
52
|
+
- [ ] **OpenCTI sync overhaul**. Improving the bidirectional sync reliability from the initial implementation.
|
|
53
|
+
- [ ] **Detection rules as first-class entities** (#feat/detection-rules-first-class branch). Sigma/YARA rules stored and searchable as knowledge graph nodes.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Backlog / on hold
|
|
58
|
+
|
|
59
|
+
These are tracked but not actively scheduled:
|
|
60
|
+
|
|
61
|
+
- **MCP registry publish** (feat/mcp-registry-publish branch). Publishing the MCP server to the official MCP registry.
|
|
62
|
+
- **Enterprise split**. Separating the current monolithic package into community + enterprise tiers. Governance, license boundary, and packaging work. Not blocked, but deferred until community adoption justifies the overhead.
|
|
63
|
+
- **TypeDB read-path hardening**. Depth routing and schema versioning for the TypeDB backend. Most users run on JSONL/SQLite; TypeDB is a small fraction of the install base.
|
|
64
|
+
- **Conversational entity extractor** (stash: feature/RFC-001-conversational-entity-extractor). Interactive refinement of extracted entities by analyst chat. Requires UX thinking and a frontend update.
|
|
65
|
+
- **Pydantic v3 upgrade prep** (stash: test-fix/pydantic-v3-prep). Preparing internal models for Pydantic v3 migration. Low urgency; no upstream pressure yet.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Out of scope (not building)
|
|
70
|
+
|
|
71
|
+
These have been proposed or discussed and explicitly decided against:
|
|
72
|
+
|
|
73
|
+
- **UI framework migration** (React, Vue, Svelte, etc.). The web GUI is a vanilla JS SPA using the ZettelForge Design System. No npm build step, no JS framework. This is intentional: the SPA must remain maintainable by a solo developer and installable with `pip install zettelforge[web]` without a separate build step. Not changing.
|
|
74
|
+
- **Docker containerization**. Deferred to v2.x post-v1.0 per the tech stack decision. The in-process architecture already makes deployment trivial.
|
|
75
|
+
- **Cloud-hosted memory backend**. ZettelForge is designed for local-first, air-gapped, and on-prem deployments. A cloud sync layer would compromise the security model and is not on the roadmap.
|
|
76
|
+
- **LangChain / LangGraph integration as a default**. Out of scope per the CLAUDE.md rules in this repo. Community wraps are welcome (see the CrewAI issue for how integration should work).
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Release cadence
|
|
81
|
+
|
|
82
|
+
- **Minor releases (v2.x.0)**: roughly every 2-3 weeks, bundling feature work and hardening.
|
|
83
|
+
- **Patch releases (v2.x.y)**: as needed for P0 bugs, security fixes, and regressions. No pre-scheduled date.
|
|
84
|
+
- **Major releases (v3.0.0+)**: not yet planned. The API is still evolving. A major version bump will come with a public deprecation notice and migration guide.
|
|
85
|
+
|
|
86
|
+
## Commitment
|
|
87
|
+
|
|
88
|
+
This roadmap is a best-effort forecast, not a contract. Priorities shift based on user feedback, security findings, and the maintainer's availability (solo maintainer, GOV-006 declared).
|
|
89
|
+
|
|
90
|
+
Issues tagged with a target release are actively planned. Issues without a release tag are candidates for the next roadmap refresh.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
[Back to README](README.md)
|
|
@@ -214,7 +214,7 @@ llm:
|
|
|
214
214
|
url: http://localhost:11434
|
|
215
215
|
api_key: ""
|
|
216
216
|
temperature: 0.1
|
|
217
|
-
timeout:
|
|
217
|
+
timeout: 180.0 # v2.5.2: bumped from 60s for reasoning-model headroom
|
|
218
218
|
max_retries: 2
|
|
219
219
|
fallback: ""
|
|
220
220
|
local_backend: llama-cpp-python # used when provider=local (RFC-011)
|
|
@@ -374,6 +374,8 @@ synthesis:
|
|
|
374
374
|
# Env overrides:
|
|
375
375
|
# ZETTELFORGE_PII_ENABLED=true
|
|
376
376
|
# ZETTELFORGE_PII_ACTION=redact
|
|
377
|
+
# ZETTELFORGE_LIMITS_MAX_CONTENT_LENGTH=104857600
|
|
378
|
+
# ZETTELFORGE_LIMITS_RECALL_TIMEOUT=60
|
|
377
379
|
#
|
|
378
380
|
governance:
|
|
379
381
|
enabled: true
|
|
@@ -385,9 +387,32 @@ governance:
|
|
|
385
387
|
entities: []
|
|
386
388
|
language: en
|
|
387
389
|
nlp_model: en_core_web_sm
|
|
390
|
+
limits:
|
|
391
|
+
max_content_length: 52428800 # 50 MB, 0 = unlimited
|
|
392
|
+
recall_timeout_seconds: 30.0 # seconds, 0 = unlimited
|
|
388
393
|
|
|
389
394
|
|
|
390
|
-
# ──
|
|
395
|
+
# ── LanceDB Maintenance (RFC-009 Phase 1.5) ─────────────────────────────────
|
|
396
|
+
# Background daemon that prunes stale LanceDB version-history per shard.
|
|
397
|
+
#
|
|
398
|
+
# Examples:
|
|
399
|
+
# # Default — clean up every hour, keep versions < 1 hour old
|
|
400
|
+
# cleanup_interval_minutes: 60
|
|
401
|
+
# cleanup_older_than_seconds: 3600
|
|
402
|
+
#
|
|
403
|
+
# # Aggressive cleanup (high-ingestion environments)
|
|
404
|
+
# cleanup_interval_minutes: 15
|
|
405
|
+
# cleanup_older_than_seconds: 600
|
|
406
|
+
#
|
|
407
|
+
# # Disable cleanup entirely
|
|
408
|
+
# cleanup_interval_minutes: 0
|
|
409
|
+
#
|
|
410
|
+
lance:
|
|
411
|
+
cleanup_interval_minutes: 60
|
|
412
|
+
cleanup_older_than_seconds: 3600
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
# ── Cache
|
|
391
416
|
# In-memory cache for TypeDB query results. Reduces round-trips for
|
|
392
417
|
# frequently accessed entities and relationships.
|
|
393
418
|
#
|
|
@@ -434,3 +459,32 @@ logging:
|
|
|
434
459
|
level: INFO
|
|
435
460
|
log_intents: true
|
|
436
461
|
log_causal: true
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
# ── Web UI (RFC-015) ─────────────────────────────────────────────────────────
|
|
465
|
+
# ZettelForge Web Management Interface — SPA served at GET /.
|
|
466
|
+
#
|
|
467
|
+
# Examples:
|
|
468
|
+
# # Default — enabled on 0.0.0.0:8088
|
|
469
|
+
# enabled: true
|
|
470
|
+
# host: 0.0.0.0
|
|
471
|
+
# port: 8088
|
|
472
|
+
#
|
|
473
|
+
# # Custom port (e.g., behind nginx reverse proxy)
|
|
474
|
+
# enabled: true
|
|
475
|
+
# host: 127.0.0.1
|
|
476
|
+
# port: 9000
|
|
477
|
+
#
|
|
478
|
+
# # Disable web UI entirely (library-only mode)
|
|
479
|
+
# enabled: false
|
|
480
|
+
#
|
|
481
|
+
# Env overrides:
|
|
482
|
+
# ZETTELFORGE_WEB_ENABLED=true
|
|
483
|
+
# ZETTELFORGE_WEB_PORT=8088
|
|
484
|
+
# ZETTELFORGE_WEB_UI_DIR=/path/to/ui
|
|
485
|
+
#
|
|
486
|
+
web:
|
|
487
|
+
enabled: true
|
|
488
|
+
host: 0.0.0.0
|
|
489
|
+
port: 8088
|
|
490
|
+
|
|
@@ -137,9 +137,9 @@ TB-1 ─────────────────────────
|
|
|
137
137
|
|
|
138
138
|
| ID | Threat | Component | Risk | Mitigation |
|
|
139
139
|
|----|--------|-----------|------|------------|
|
|
140
|
-
| D-01 | Large content in `remember()` exhausts memory or blocks the enrichment queue | MemoryManager (P1) | **
|
|
140
|
+
| D-01 | Large content in `remember()` exhausts memory or blocks the enrichment queue | MemoryManager (P1) | **Low** — gracefully rejected | `governance.limits.max_content_length` (RFC-014, default 50 MB) blocks oversized content with a clear error. `remember_report()` chunks long documents. Enrichment queue has `maxsize=500` backpressure. |
|
|
141
141
|
| D-02 | LLM provider (ollama, litellm) hangs and blocks `remember()` | LLM Provider (TB-4) | **High** — operation blocks | OllamaProvider has timeout (RFC-010, default 60s). LitellmProvider has timeout + num_retries. `generate()` returns empty string on recoverable failure. Fallback provider (e.g., local -> ollama) gives alternative path. |
|
|
142
|
-
| D-03 | Malicious query triggers deep graph traversal exhausting time/resources | BlendedRetriever | **Medium** —
|
|
142
|
+
| D-03 | Malicious query triggers deep graph traversal exhausting time/resources | BlendedRetriever | **Medium** — bounded, but timeout may still block | `governance.limits.recall_timeout_seconds` (RFC-014, default 30s) applies a wall-clock timeout to the recall pipeline, but the current `ThreadPoolExecutor`-based approach must not be treated as guaranteeing prompt return on timeout. `max_graph_depth` (default 2) limits BFS hops. `default_k` (default 10) limits results. Reclassify to **Low** only after the timeout path is verified to return promptly and log `recall_timed_out` without waiting for the running task to finish. |
|
|
143
143
|
| D-04 | spaCy model download blocks first `remember()` when PII is enabled | PIIValidator (lazy load) | **Low** — delayed first call (~2-3 seconds) | One-time download cost. Matching fastembed pattern. Can be pre-downloaded for air-gapped deployments. |
|
|
144
144
|
|
|
145
145
|
### 2.6 Elevation of Privilege
|
|
@@ -158,8 +158,8 @@ TB-1 ─────────────────────────
|
|
|
158
158
|
|------------|-------|--------------|
|
|
159
159
|
| **Critical** | 2 | T-01 (storage tampering), I-01 (unencrypted data at rest), E-02 (governance bypass via filesystem) |
|
|
160
160
|
| **High** | 7 | S-01 (spoofed MCP client), S-03 (config tampering), T-02 (config security downgrade), R-01 (repudiation without audit), I-02 (PII in stored notes), D-02 (LLM provider hang), E-01 (cross-tenant data access) |
|
|
161
|
-
| **Medium** |
|
|
162
|
-
| **Low** |
|
|
161
|
+
| **Medium** | 7 | S-02 (fake LLM provider), T-04 (retrieval poisoning), R-02, R-03, I-04 (error message leakage), E-03 |
|
|
162
|
+
| **Low** | 3 | D-01, D-03, D-04 (PII model download delay) |
|
|
163
163
|
|
|
164
164
|
### Top 5 Mitigations (Priority Order)
|
|
165
165
|
|
|
@@ -181,6 +181,8 @@ TB-1 ─────────────────────────
|
|
|
181
181
|
| API key redaction | I-03 | `LLMConfig.__repr__` redacts api_key and sensitive extra keys | Unit tests in `test_llm_providers.py` |
|
|
182
182
|
| PII detection + redaction | I-02 | PIIValidator (RFC-013): log/redact/block | Unit tests in `test_pii_validator.py` |
|
|
183
183
|
| LLM provider timeout | D-02 | `OllamaProvider` timeout=60s, `LiteLLMProvider` timeout + num_retries | Unit tests (RFC-010, RFC-012) |
|
|
184
|
+
| Content size limit | D-01 | `governance.limits.max_content_length` (RFC-014, default 50 MB) blocks oversized content | Unit tests in `test_governance.py` |
|
|
185
|
+
| Recall timeout | D-03 | `governance.limits.recall_timeout_seconds` (RFC-014, default 30s) wraps recall in ThreadPoolExecutor with wall-clock timeout | Unit tests in `test_governance.py` |
|
|
184
186
|
| Config env-var resolution | I-03 | `${ENV_VAR}` syntax prevents raw secrets in YAML | Unit tests |
|
|
185
187
|
| Configurable model provider | S-02, E-03 | `provider` key selects backend; no implicit unauthenticated outbound calls | Config validation |
|
|
186
188
|
| Enrichment queue backpressure | D-01 | `maxsize=500` bounded queue | Code review |
|
|
@@ -189,7 +191,6 @@ TB-1 ─────────────────────────
|
|
|
189
191
|
|
|
190
192
|
| Recommendation | Threat(s) | Effort | Priority |
|
|
191
193
|
|---------------|-----------|--------|----------|
|
|
192
|
-
| Add content size limit to `remember()` | D-01 | Small | P3 |
|
|
193
194
|
| Add global exception handler that sanitizes error output | I-04 | Medium | P2 |
|
|
194
195
|
| Add TLS verification option for self-hosted LLM endpoints | S-02 | Small | P2 |
|
|
195
196
|
| Add config file integrity check (SHA-256 of default vs. loaded) | T-02, S-03 | Medium | P3 |
|
|
@@ -231,6 +232,7 @@ Per GOV-021, the following data types exist in the system:
|
|
|
231
232
|
|
|
232
233
|
| Change | RFC/PR | Date | Threat Model Impact |
|
|
233
234
|
|--------|--------|------|---------------------|
|
|
235
|
+
| Content size limits + recall timeout | RFC-014 | 2026-04-25 | Mitigation for D-01 (content size limit, default 50 MB); partial mitigation for D-03 (timeout) |
|
|
234
236
|
| PII detection and redaction | RFC-013 (PR #118) | 2026-04-25 | New control for I-02; new attack surface (D-04); PII text logging fixed |
|
|
235
237
|
| LiteLLM unified provider | RFC-012 (PR #108) | 2026-04-25 | New provider for I-03 (API keys); new outbound traffic pattern (TB-4) |
|
|
236
238
|
| Local LLM backend selection | RFC-011 (PR #104) | 2026-04-25 | No new threat surface — extends existing local provider |
|