kognita 0.2.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.
- kognita-0.2.0/.gitignore +210 -0
- kognita-0.2.0/LICENSE +21 -0
- kognita-0.2.0/PKG-INFO +275 -0
- kognita-0.2.0/README.md +214 -0
- kognita-0.2.0/examples/local_embedding_server/README.md +36 -0
- kognita-0.2.0/examples/local_embedding_server/server.py +76 -0
- kognita-0.2.0/examples/streamlit_app/README.md +30 -0
- kognita-0.2.0/examples/streamlit_app/app.py +2073 -0
- kognita-0.2.0/examples/streamlit_app/static/images/kognita.png +0 -0
- kognita-0.2.0/pyproject.toml +170 -0
- kognita-0.2.0/src/kognita/__init__.py +249 -0
- kognita-0.2.0/src/kognita/adapters/__init__.py +15 -0
- kognita-0.2.0/src/kognita/adapters/embeddings.py +102 -0
- kognita-0.2.0/src/kognita/approvals.py +394 -0
- kognita-0.2.0/src/kognita/broker.py +226 -0
- kognita-0.2.0/src/kognita/canonical.py +52 -0
- kognita-0.2.0/src/kognita/classify.py +131 -0
- kognita-0.2.0/src/kognita/cli.py +183 -0
- kognita-0.2.0/src/kognita/config.py +174 -0
- kognita-0.2.0/src/kognita/db.py +86 -0
- kognita-0.2.0/src/kognita/egress.py +318 -0
- kognita-0.2.0/src/kognita/embedding.py +110 -0
- kognita-0.2.0/src/kognita/envelope.py +186 -0
- kognita-0.2.0/src/kognita/evidence.py +296 -0
- kognita-0.2.0/src/kognita/exceptions.py +40 -0
- kognita-0.2.0/src/kognita/governance.py +315 -0
- kognita-0.2.0/src/kognita/graph/__init__.py +63 -0
- kognita-0.2.0/src/kognita/graph/chunking.py +26 -0
- kognita-0.2.0/src/kognita/graph/config.py +59 -0
- kognita-0.2.0/src/kognita/graph/driver.py +199 -0
- kognita-0.2.0/src/kognita/graph/engine.py +305 -0
- kognita-0.2.0/src/kognita/graph/query.py +53 -0
- kognita-0.2.0/src/kognita/graph/session.py +168 -0
- kognita-0.2.0/src/kognita/graph/storage.py +129 -0
- kognita-0.2.0/src/kognita/graph/sync.py +64 -0
- kognita-0.2.0/src/kognita/graph/types.py +67 -0
- kognita-0.2.0/src/kognita/models.py +336 -0
- kognita-0.2.0/src/kognita/protocols.py +137 -0
- kognita-0.2.0/src/kognita/registry.py +90 -0
- kognita-0.2.0/src/kognita/retrieval.py +227 -0
- kognita-0.2.0/src/kognita/rules.py +222 -0
- kognita-0.2.0/src/kognita/testing/__init__.py +25 -0
- kognita-0.2.0/src/kognita/testing/conformance.py +316 -0
- kognita-0.2.0/src/kognita/testing/harness.py +118 -0
- kognita-0.2.0/src/kognita/tools.py +213 -0
- kognita-0.2.0/src/kognita/vectors.py +136 -0
- kognita-0.2.0/src/kognita/vocabulary.py +117 -0
- kognita-0.2.0/tests/conftest.py +53 -0
- kognita-0.2.0/tests/fixtures/__init__.py +0 -0
- kognita-0.2.0/tests/fixtures/bmos_pack.py +281 -0
- kognita-0.2.0/tests/fixtures/demo_pack.py +390 -0
- kognita-0.2.0/tests/test_bmos_conformance.py +401 -0
- kognita-0.2.0/tests/test_conformance.py +446 -0
- kognita-0.2.0/tests/test_core.py +595 -0
- kognita-0.2.0/tests/test_packaging.py +121 -0
kognita-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
#poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
#pdm.lock
|
|
116
|
+
#pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
#pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# SageMath parsed files
|
|
135
|
+
*.sage.py
|
|
136
|
+
|
|
137
|
+
# Environments
|
|
138
|
+
.env
|
|
139
|
+
.envrc
|
|
140
|
+
.venv
|
|
141
|
+
env/
|
|
142
|
+
venv/
|
|
143
|
+
ENV/
|
|
144
|
+
env.bak/
|
|
145
|
+
venv.bak/
|
|
146
|
+
|
|
147
|
+
# Spyder project settings
|
|
148
|
+
.spyderproject
|
|
149
|
+
.spyproject
|
|
150
|
+
|
|
151
|
+
# Rope project settings
|
|
152
|
+
.ropeproject
|
|
153
|
+
|
|
154
|
+
# mkdocs documentation
|
|
155
|
+
/site
|
|
156
|
+
|
|
157
|
+
# mypy
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.dmypy.json
|
|
160
|
+
dmypy.json
|
|
161
|
+
|
|
162
|
+
# Pyre type checker
|
|
163
|
+
.pyre/
|
|
164
|
+
|
|
165
|
+
# pytype static type analyzer
|
|
166
|
+
.pytype/
|
|
167
|
+
|
|
168
|
+
# Cython debug symbols
|
|
169
|
+
cython_debug/
|
|
170
|
+
|
|
171
|
+
# PyCharm
|
|
172
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
173
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
174
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
175
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
176
|
+
#.idea/
|
|
177
|
+
|
|
178
|
+
# Abstra
|
|
179
|
+
# Abstra is an AI-powered process automation framework.
|
|
180
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
181
|
+
# Learn more at https://abstra.io/docs
|
|
182
|
+
.abstra/
|
|
183
|
+
|
|
184
|
+
# Visual Studio Code
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
189
|
+
# .vscode/
|
|
190
|
+
|
|
191
|
+
# Ruff stuff:
|
|
192
|
+
.ruff_cache/
|
|
193
|
+
|
|
194
|
+
# PyPI configuration file
|
|
195
|
+
.pypirc
|
|
196
|
+
|
|
197
|
+
# Cursor
|
|
198
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
199
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
200
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
201
|
+
.cursorignore
|
|
202
|
+
.cursorindexingignore
|
|
203
|
+
|
|
204
|
+
# Marimo
|
|
205
|
+
marimo/_static/
|
|
206
|
+
marimo/_lsp/
|
|
207
|
+
__marimo__/
|
|
208
|
+
|
|
209
|
+
# Local graph data storage (added by Kognita for caching processed graphs)
|
|
210
|
+
.saved_graphs/
|
kognita-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ahmed Muzammil
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
kognita-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: kognita
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Prove an AI answer was permitted — and evidence it. A governed decision, retrieval and knowledge-graph library.
|
|
5
|
+
Project-URL: Homepage, https://github.com/mze3e/kognita
|
|
6
|
+
Project-URL: Repository, https://github.com/mze3e/kognita
|
|
7
|
+
Project-URL: Issues, https://github.com/mze3e/kognita/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/mze3e/kognita/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Ahmed Muzammil
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: audit,compliance,governance,graphiti,knowledge-graph,kuzu,policy-decision-point,rag
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
16
|
+
Classifier: Intended Audience :: Legal Industry
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Security
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Requires-Dist: numpy>=1.26.0
|
|
25
|
+
Requires-Dist: pydantic>=2.7.0
|
|
26
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
27
|
+
Requires-Dist: sqlmodel>=0.0.22
|
|
28
|
+
Provides-Extra: all
|
|
29
|
+
Requires-Dist: fastapi>=0.115.0; extra == 'all'
|
|
30
|
+
Requires-Dist: graphiti-core[anthropic]==0.28.2; extra == 'all'
|
|
31
|
+
Requires-Dist: graphiti-core[google-genai]==0.28.2; extra == 'all'
|
|
32
|
+
Requires-Dist: graphiti-core[groq]==0.28.2; extra == 'all'
|
|
33
|
+
Requires-Dist: graphiti-core[kuzu]==0.28.2; extra == 'all'
|
|
34
|
+
Requires-Dist: kuzu==0.11.3; extra == 'all'
|
|
35
|
+
Requires-Dist: openai<2,>=1.91.0; extra == 'all'
|
|
36
|
+
Requires-Dist: sentence-transformers>=3.0.0; extra == 'all'
|
|
37
|
+
Requires-Dist: sqlite-vec>=0.1.6; extra == 'all'
|
|
38
|
+
Requires-Dist: uvicorn>=0.30.0; extra == 'all'
|
|
39
|
+
Provides-Extra: anthropic
|
|
40
|
+
Requires-Dist: graphiti-core[anthropic]==0.28.2; extra == 'anthropic'
|
|
41
|
+
Provides-Extra: dev
|
|
42
|
+
Requires-Dist: import-linter>=2.0; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
44
|
+
Provides-Extra: gemini
|
|
45
|
+
Requires-Dist: graphiti-core[google-genai]==0.28.2; extra == 'gemini'
|
|
46
|
+
Provides-Extra: graph
|
|
47
|
+
Requires-Dist: graphiti-core[kuzu]==0.28.2; extra == 'graph'
|
|
48
|
+
Requires-Dist: kuzu==0.11.3; extra == 'graph'
|
|
49
|
+
Requires-Dist: openai<2,>=1.91.0; extra == 'graph'
|
|
50
|
+
Provides-Extra: groq
|
|
51
|
+
Requires-Dist: graphiti-core[groq]==0.28.2; extra == 'groq'
|
|
52
|
+
Provides-Extra: local-embeddings
|
|
53
|
+
Requires-Dist: fastapi>=0.115.0; extra == 'local-embeddings'
|
|
54
|
+
Requires-Dist: sentence-transformers>=3.0.0; extra == 'local-embeddings'
|
|
55
|
+
Requires-Dist: uvicorn>=0.30.0; extra == 'local-embeddings'
|
|
56
|
+
Provides-Extra: openai
|
|
57
|
+
Requires-Dist: openai<2,>=1.91.0; extra == 'openai'
|
|
58
|
+
Provides-Extra: vec
|
|
59
|
+
Requires-Dist: sqlite-vec>=0.1.6; extra == 'vec'
|
|
60
|
+
Description-Content-Type: text/markdown
|
|
61
|
+
|
|
62
|
+
# Kognita
|
|
63
|
+
|
|
64
|
+
[](https://pypi.org/project/kognita/)
|
|
65
|
+
[](https://pypi.org/project/kognita/)
|
|
66
|
+
[](https://opensource.org/licenses/MIT)
|
|
67
|
+
[](https://github.com/mze3e/kognita/actions/workflows/ci.yml)
|
|
68
|
+
[](https://pepy.tech/project/kognita)
|
|
69
|
+
|
|
70
|
+
**Prove an AI answer was permitted — and evidence it.**
|
|
71
|
+
|
|
72
|
+
| You want to… | Reach for |
|
|
73
|
+
|---|---|
|
|
74
|
+
| Connect fragmented files and databases quickly | LlamaIndex |
|
|
75
|
+
| Build complex, customised LLM workflows | LangChain |
|
|
76
|
+
| Create a team of specialised agents | CrewAI |
|
|
77
|
+
| Map complex relationships across data | GraphRAG |
|
|
78
|
+
| **Prove an answer was permitted, and evidence it** | **Kognita** |
|
|
79
|
+
|
|
80
|
+
Content guardrails filter *what a model says*. Kognita decides *whether the
|
|
81
|
+
request was allowed — before any data is retrieved* — and writes the record.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from kognita import Envelope, decide, load_snapshot
|
|
85
|
+
|
|
86
|
+
evaluation = decide(
|
|
87
|
+
Envelope(principal="rm@bank.example", purpose="ELIGIBILITY_CHECK",
|
|
88
|
+
tool="check_eligibility", actor_location="AE",
|
|
89
|
+
subject_type="client", subject_id="1",
|
|
90
|
+
subjects={"instrument": "1"}),
|
|
91
|
+
load_snapshot(session),
|
|
92
|
+
attributes=pack.resolve_attributes(...),
|
|
93
|
+
rules=pack.rules(),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
evaluation.outcome # DENY
|
|
97
|
+
for check in evaluation.basis():
|
|
98
|
+
print(check.regime, check.citation)
|
|
99
|
+
# HK_SFC SFC Code of Conduct para 5.5
|
|
100
|
+
# DIFC_DFSA DFSA COB 3; GEN 2
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Two independent regimes refused; neither masked the other; each names the rule
|
|
104
|
+
it came from. Nothing was retrieved.
|
|
105
|
+
|
|
106
|
+
## Install
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install kognita # the decision engine — 4 dependencies
|
|
110
|
+
pip install kognita[graph] # + Graphiti/Kuzu knowledge graph
|
|
111
|
+
pip install kognita[openai] # + a real embedder
|
|
112
|
+
pip install kognita[all]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The core installs on `pydantic`, `sqlmodel`, `numpy` and `python-dotenv`, and
|
|
116
|
+
runs with no network and no API key. Deciding whether a request is permitted
|
|
117
|
+
should not require the machinery that answers it — and that constraint is
|
|
118
|
+
enforced by `import-linter` contracts plus a test that installs with no extras
|
|
119
|
+
and asserts `decide()` still runs.
|
|
120
|
+
|
|
121
|
+
## What it does
|
|
122
|
+
|
|
123
|
+
**Authorise before discovery.** An envelope describes an intent and is evaluated
|
|
124
|
+
before anything is fetched. A denial returns no data, not filtered data.
|
|
125
|
+
|
|
126
|
+
**Fail closed.** `DENY > ESCALATE > HUMAN_APPROVAL > ALLOW`. One failing check
|
|
127
|
+
among a hundred passes still denies, so a policy set cannot be widened by adding
|
|
128
|
+
permissive rules.
|
|
129
|
+
|
|
130
|
+
**Every decision cites its rule.** A check without a citation is an assertion,
|
|
131
|
+
not a decision; the conformance kit enforces it.
|
|
132
|
+
|
|
133
|
+
**Decisions are pure and replayable.** `decide()` writes nothing and takes the
|
|
134
|
+
instant as a parameter, so *"what would this have decided in March?"* has an
|
|
135
|
+
answer:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
decide(envelope, snapshot, as_of=datetime(2026, 3, 1, tzinfo=timezone.utc))
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Evidence is tamper-evident.** Each event carries the previous event's hash.
|
|
142
|
+
Altering any payload breaks every hash after it:
|
|
143
|
+
|
|
144
|
+
```console
|
|
145
|
+
$ kognita evidence verify --db store.db
|
|
146
|
+
BROKEN: evidence chain broken at sequence 2: payload does not match its hash
|
|
147
|
+
|
|
148
|
+
$ kognita evidence export --db store.db -o audit.json # portable, self-verifying
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Payloads hold hashes and references by default — an append-only log full of
|
|
152
|
+
personal data collides with erasure rights — and `hashes_only` strips content
|
|
153
|
+
entirely while keeping the log provable.
|
|
154
|
+
|
|
155
|
+
**Egress is guarded, not merely refused.** A binary local-or-refuse rule confines
|
|
156
|
+
a governed system to whatever model runs on the box. The guard adds redaction:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
result = guard.send(text, call_the_model,
|
|
160
|
+
classification=Classification.C2,
|
|
161
|
+
destination="api.openai.com", destination_is_local=False)
|
|
162
|
+
|
|
163
|
+
result.decision # REDACT
|
|
164
|
+
# the provider saw: [TERM_1] ([EMAIL_1]) holds account [ACCOUNT_1]
|
|
165
|
+
# the caller got the real values back, and MODEL_CALL + EGRESS
|
|
166
|
+
# record the manifest hash — never the content.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
> `PatternRedactor` is a floor, not a guarantee. Regexes miss names in prose and
|
|
170
|
+
> anything the patterns do not anticipate. Deployments handling real personal
|
|
171
|
+
> data should supply an NER-based `Redactor`; the tests cover the plumbing —
|
|
172
|
+
> that nothing unredacted escapes the guard — never detection recall.
|
|
173
|
+
|
|
174
|
+
## Domain packs
|
|
175
|
+
|
|
176
|
+
The core is domain-blind. A pack supplies the two things it cannot know: what a
|
|
177
|
+
request's *attributes* are, and how to load the *subjects* it refers to.
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
class MyPack:
|
|
181
|
+
name = "my-domain"
|
|
182
|
+
def load_subjects(self, envelope, session): ...
|
|
183
|
+
def resolve_attributes(self, envelope, subjects): ...
|
|
184
|
+
def rules(self): return build_registry(MY_EVALUATORS)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Policies are data — effective-dated rows with a JSON payload interpreted by the
|
|
188
|
+
evaluator registered for their `rule_type`. The core ships five primitives
|
|
189
|
+
(allowlist, denylist, required flag, required human review, prohibited); a pack
|
|
190
|
+
registers whatever its regimes need beyond them. A policy whose `rule_type` has
|
|
191
|
+
no evaluator **escalates** rather than being skipped: it is a rule someone
|
|
192
|
+
believes is in force.
|
|
193
|
+
|
|
194
|
+
### Conformance
|
|
195
|
+
|
|
196
|
+
Kognita ships a conformance kit: a set of assertions that every domain pack must
|
|
197
|
+
satisfy. The kit proves that whatever a pack's regimes say, they are decided
|
|
198
|
+
fail-closed, cited, and evidenced.
|
|
199
|
+
|
|
200
|
+
Run the kit over the bundled fixture pack (proves the kit itself works):
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pytest --pyargs kognita.testing.conformance
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Or subclass it in your own pack's test suite:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from kognita.testing import ConformanceCase, Harness
|
|
210
|
+
|
|
211
|
+
class TestMyPack(ConformanceCase):
|
|
212
|
+
@pytest.fixture(autouse=True)
|
|
213
|
+
def _bind(self):
|
|
214
|
+
self.harness = Harness(pack=MyPack(), purposes=PURPOSES, seed=seed)
|
|
215
|
+
self.allow_envelope = Envelope(...)
|
|
216
|
+
self.deny_envelope = Envelope(...)
|
|
217
|
+
self.human_envelope = Envelope(...) # optional
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The pattern follows `langchain-tests`: invariants are importable and reusable by
|
|
221
|
+
external packs running in their own repositories.
|
|
222
|
+
|
|
223
|
+
## The knowledge graph
|
|
224
|
+
|
|
225
|
+
`kognita[graph]` adds the Graphiti + Kuzu engine: documents become a bi-temporal,
|
|
226
|
+
auto-deduplicated knowledge graph.
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
from kognita.graph import GraphEngine, GraphConfig
|
|
230
|
+
|
|
231
|
+
async with GraphEngine(config) as kg:
|
|
232
|
+
await kg.ingest_text(document, source="policy-handbook")
|
|
233
|
+
hits = await kg.search("cross-border disclosure")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Two graphs share one Kuzu database: Graphiti's LLM-extracted knowledge, and a
|
|
237
|
+
deterministic `SoR_*` mirror of a system of record, so one traversal crosses both
|
|
238
|
+
planes. All access goes through a single `KuzuSession` — two `kuzu.Database`
|
|
239
|
+
handles on one path do **not** share a consistent view and raise nothing when
|
|
240
|
+
they diverge. See [docs/decisions/0001-kuzu-cotenancy.md](docs/decisions/0001-kuzu-cotenancy.md).
|
|
241
|
+
|
|
242
|
+
## Layout
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
kognita the decision engine — decisions, evidence, retrieval,
|
|
246
|
+
egress, tools. Four dependencies, no network.
|
|
247
|
+
kognita.graph Graphiti + Kuzu knowledge engine [graph]
|
|
248
|
+
kognita.adapters provider-backed embedders and clients [openai] …
|
|
249
|
+
kognita.testing the conformance kit
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`kognita` **is** the decision engine, not a namespace that points at one. No
|
|
253
|
+
graph name is reachable from it: the graph is imported from `kognita.graph`, so
|
|
254
|
+
reading an import tells you whether a graph database is about to be loaded.
|
|
255
|
+
`import kognita` never loads one, and `tests/test_packaging.py` asserts it.
|
|
256
|
+
|
|
257
|
+
> **Moved in 0.2.** `kognita.Kognita` → `kognita.graph.GraphEngine`,
|
|
258
|
+
> `kognita.KognitaConfig` → `kognita.graph.GraphConfig`,
|
|
259
|
+
> `kognita.KognitaKuzuDriver` → `kognita.graph.KuzuDriver`, and
|
|
260
|
+
> `kognita.core.*` → `kognita.*`. Touching a retired name raises an
|
|
261
|
+
> `AttributeError` naming the module that now owns it. Reasoning and the full
|
|
262
|
+
> migration table: [docs/decisions/0003-the-top-level-namespace.md](docs/decisions/0003-the-top-level-namespace.md).
|
|
263
|
+
|
|
264
|
+
## Status
|
|
265
|
+
|
|
266
|
+
**Alpha. Phases 0–5 complete:** core packaging, governance, evidence chain,
|
|
267
|
+
retrieval, egress guard, tool runner, broker, conformance kit, and adapters.
|
|
268
|
+
|
|
269
|
+
**Phase 6 in progress:** deterministic graph mirror (SoR_* tables), governed
|
|
270
|
+
document ingestion with evidence logging, and cross-plane Cypher (REFERENCES
|
|
271
|
+
edges linking knowledge graph to system of record).
|
|
272
|
+
|
|
273
|
+
**Phase 7 pending:** final release, performance benchmarks, docs rewrite, v0.2.0.
|
|
274
|
+
|
|
275
|
+
MIT licensed.
|