ct-toolkit 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ct_toolkit-0.2.1/PKG-INFO +119 -0
- ct_toolkit-0.2.1/README.md +82 -0
- ct_toolkit-0.2.1/ct_toolkit/divergence/analysis.py +149 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/divergence/engine.py +22 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/divergence/l3_icm.py +44 -5
- ct_toolkit-0.2.1/ct_toolkit.egg-info/PKG-INFO +119 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit.egg-info/SOURCES.txt +3 -1
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/pyproject.toml +1 -1
- ct_toolkit-0.2.1/tests/test_analysis.py +69 -0
- ct_toolkit-0.2.0/PKG-INFO +0 -367
- ct_toolkit-0.2.0/README.md +0 -330
- ct_toolkit-0.2.0/ct_toolkit.egg-info/PKG-INFO +0 -367
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/LICENSE +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/core/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/core/compatibility.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/core/exceptions.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/core/kernel.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/core/wrapper.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/divergence/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/divergence/l2_judge.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/divergence/scheduler.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/endorsement/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/endorsement/probes/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/endorsement/reflective.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/identity/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/identity/embedding.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/middleware/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/middleware/autogen.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/middleware/crewai.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/middleware/langchain.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/provenance/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/provenance/log.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/provenance/vault/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/utils/__init__.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit/utils/logger.py +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit.egg-info/dependency_links.txt +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit.egg-info/requires.txt +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/ct_toolkit.egg-info/top_level.txt +0 -0
- {ct_toolkit-0.2.0 → ct_toolkit-0.2.1}/setup.cfg +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ct-toolkit
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems
|
|
5
|
+
Author: Hakan Damar
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: llm,ai-safety,identity-continuity,guardrails,alignment
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: instructor>=1.3.0
|
|
12
|
+
Requires-Dist: any-llm-sdk[all]>=1.0.0
|
|
13
|
+
Requires-Dist: numpy>=1.26.0
|
|
14
|
+
Requires-Dist: pyyaml>=6.0
|
|
15
|
+
Requires-Dist: pydantic>=2.5.0
|
|
16
|
+
Requires-Dist: cryptography>=42.0.0
|
|
17
|
+
Requires-Dist: SQLAlchemy>=2.0.0
|
|
18
|
+
Requires-Dist: httpx>=0.27.0
|
|
19
|
+
Requires-Dist: rich>=13.0.0
|
|
20
|
+
Requires-Dist: jinja2>=3.1.0
|
|
21
|
+
Provides-Extra: ollama
|
|
22
|
+
Requires-Dist: ollama>=0.2.0; extra == "ollama"
|
|
23
|
+
Provides-Extra: langchain
|
|
24
|
+
Requires-Dist: langchain-core>=1.2.0; extra == "langchain"
|
|
25
|
+
Provides-Extra: crewai
|
|
26
|
+
Requires-Dist: crewai>=1.10.0; extra == "crewai"
|
|
27
|
+
Provides-Extra: autogen
|
|
28
|
+
Requires-Dist: pyautogen>=0.4.0; extra == "autogen"
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# Computational Theseus Toolkit (CT Toolkit)
|
|
39
|
+
|
|
40
|
+
> **Identity Continuity Guardrails for Agentic Systems**
|
|
41
|
+
|
|
42
|
+
[](https://www.python.org/)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
[](https://badge.fury.io/py/ct-toolkit)
|
|
45
|
+
[](https://hakandamar.github.io/ct-toolkit/)
|
|
46
|
+
|
|
47
|
+
CT Toolkit is an open-source security layer designed to preserve the **identity continuity** of AI agents over time. It implements the **Nested Agency Architecture (NAA)** framework to prevent **Sequential Self-Compression (SSC)** in multi-agent hierarchies.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 📖 Official Documentation
|
|
52
|
+
For full API reference, architecture details, and integration guides, visit our documentation site:
|
|
53
|
+
👉 [**https://hakandamar.github.io/ct-toolkit/**](https://hakandamar.github.io/ct-toolkit/)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Why CT Toolkit?
|
|
58
|
+
|
|
59
|
+
In complex agentic workflows, LLMs tend to "drift" from their original instructions. CT Toolkit provides the mathematical and cryptographic guardrails to ensure your agents remain aligned with their core constitution, even across deep hierarchies.
|
|
60
|
+
|
|
61
|
+
- **Constitutional Kernels**: Axiomatic identity anchors.
|
|
62
|
+
- **Divergence Engine**: Multi-tiered drift analysis (L1/L2/L3).
|
|
63
|
+
- **Hierarchical Propagation**: Mother-to-child constraint inheritance.
|
|
64
|
+
- **Provenance Log**: Immutable HMAC-signed interaction history.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Quick Start
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install ct-toolkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from ct_toolkit import TheseusWrapper
|
|
76
|
+
|
|
77
|
+
# One-line injection for any LLM provider
|
|
78
|
+
client = TheseusWrapper(provider="openai")
|
|
79
|
+
|
|
80
|
+
# Guardrails and drift analysis applied automatically
|
|
81
|
+
response = client.chat("What are your core security axioms?")
|
|
82
|
+
|
|
83
|
+
print(response.content)
|
|
84
|
+
print(f"Divergence Score: {response.divergence_score}")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🚦 Project Health & Status
|
|
90
|
+
|
|
91
|
+
| Metric | Status |
|
|
92
|
+
| :--- | :--- |
|
|
93
|
+
| **Tests** | ✅ 202/203 passing (92% coverage) |
|
|
94
|
+
| **Last Phase** | ✅ Phase 3: ICM and Measurement (Complete) |
|
|
95
|
+
| **Current Goal** | 🔶 Phase 4: Open-Source Support |
|
|
96
|
+
|
|
97
|
+
For a detailed breakdown of the 8-phase roadmap, see [**PROJECT_STATUS.md**](docs/PROJECT_STATUS.md).
|
|
98
|
+
|
|
99
|
+
### Framework Support
|
|
100
|
+
Seamlessly integrate with your favorite frameworks:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
# LangChain
|
|
104
|
+
from ct_toolkit.middleware.langchain import TheseusChatModel
|
|
105
|
+
llm = TheseusChatModel(provider="openai")
|
|
106
|
+
|
|
107
|
+
# CrewAI
|
|
108
|
+
TheseusCrewMiddleware.apply_to_crew(crew, manager_wrapper)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Theoretical Foundation
|
|
114
|
+
Translating the framework proposed in [**The Computational Theseus (2025)**](https://hakandamar.com/the-computational-theseus-engineering-identity-continuity-as-a-guardrail-against-sequential-963918c1720d) into engineering practice.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
Apache License 2.0.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Computational Theseus Toolkit (CT Toolkit)
|
|
2
|
+
|
|
3
|
+
> **Identity Continuity Guardrails for Agentic Systems**
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://badge.fury.io/py/ct-toolkit)
|
|
8
|
+
[](https://hakandamar.github.io/ct-toolkit/)
|
|
9
|
+
|
|
10
|
+
CT Toolkit is an open-source security layer designed to preserve the **identity continuity** of AI agents over time. It implements the **Nested Agency Architecture (NAA)** framework to prevent **Sequential Self-Compression (SSC)** in multi-agent hierarchies.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 📖 Official Documentation
|
|
15
|
+
For full API reference, architecture details, and integration guides, visit our documentation site:
|
|
16
|
+
👉 [**https://hakandamar.github.io/ct-toolkit/**](https://hakandamar.github.io/ct-toolkit/)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why CT Toolkit?
|
|
21
|
+
|
|
22
|
+
In complex agentic workflows, LLMs tend to "drift" from their original instructions. CT Toolkit provides the mathematical and cryptographic guardrails to ensure your agents remain aligned with their core constitution, even across deep hierarchies.
|
|
23
|
+
|
|
24
|
+
- **Constitutional Kernels**: Axiomatic identity anchors.
|
|
25
|
+
- **Divergence Engine**: Multi-tiered drift analysis (L1/L2/L3).
|
|
26
|
+
- **Hierarchical Propagation**: Mother-to-child constraint inheritance.
|
|
27
|
+
- **Provenance Log**: Immutable HMAC-signed interaction history.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install ct-toolkit
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from ct_toolkit import TheseusWrapper
|
|
39
|
+
|
|
40
|
+
# One-line injection for any LLM provider
|
|
41
|
+
client = TheseusWrapper(provider="openai")
|
|
42
|
+
|
|
43
|
+
# Guardrails and drift analysis applied automatically
|
|
44
|
+
response = client.chat("What are your core security axioms?")
|
|
45
|
+
|
|
46
|
+
print(response.content)
|
|
47
|
+
print(f"Divergence Score: {response.divergence_score}")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚦 Project Health & Status
|
|
53
|
+
|
|
54
|
+
| Metric | Status |
|
|
55
|
+
| :--- | :--- |
|
|
56
|
+
| **Tests** | ✅ 202/203 passing (92% coverage) |
|
|
57
|
+
| **Last Phase** | ✅ Phase 3: ICM and Measurement (Complete) |
|
|
58
|
+
| **Current Goal** | 🔶 Phase 4: Open-Source Support |
|
|
59
|
+
|
|
60
|
+
For a detailed breakdown of the 8-phase roadmap, see [**PROJECT_STATUS.md**](docs/PROJECT_STATUS.md).
|
|
61
|
+
|
|
62
|
+
### Framework Support
|
|
63
|
+
Seamlessly integrate with your favorite frameworks:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
# LangChain
|
|
67
|
+
from ct_toolkit.middleware.langchain import TheseusChatModel
|
|
68
|
+
llm = TheseusChatModel(provider="openai")
|
|
69
|
+
|
|
70
|
+
# CrewAI
|
|
71
|
+
TheseusCrewMiddleware.apply_to_crew(crew, manager_wrapper)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Theoretical Foundation
|
|
77
|
+
Translating the framework proposed in [**The Computational Theseus (2025)**](https://hakandamar.com/the-computational-theseus-engineering-identity-continuity-as-a-guardrail-against-sequential-963918c1720d) into engineering practice.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
Apache License 2.0.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ct_toolkit.divergence.analysis
|
|
3
|
+
-------------------------------
|
|
4
|
+
Policy-Drift Measurement and SSC Severity Operationalization.
|
|
5
|
+
|
|
6
|
+
This module provides tools to analyze the Provenance Log for longitudinal
|
|
7
|
+
identity stability, identifying Sequential Self-Compression (SSC) patterns.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import math
|
|
12
|
+
import numpy as np
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from typing import TYPE_CHECKING, Any
|
|
15
|
+
|
|
16
|
+
from ct_toolkit.utils.logger import get_logger
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from ct_toolkit.provenance.log import ProvenanceLog, ProvenanceEntry
|
|
20
|
+
from ct_toolkit.divergence.scheduler import RiskProfile
|
|
21
|
+
|
|
22
|
+
logger = get_logger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class DriftReport:
|
|
27
|
+
"""Longitudinal drift analysis report."""
|
|
28
|
+
mean_divergence: float
|
|
29
|
+
divergence_variance: float
|
|
30
|
+
drift_velocity: float # Change in divergence per session
|
|
31
|
+
ssc_severity_score: float # Normalized 0.0 - 1.0 (SSC Severity Index)
|
|
32
|
+
structural_risk_score: float # Base risk score from capabilities (0.0 - 1.0)
|
|
33
|
+
is_ssc_suspected: bool
|
|
34
|
+
data_points: int
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class PolicyDriftAnalyzer:
|
|
38
|
+
"""
|
|
39
|
+
Analyzes distributional shifts in an agent's decision boundaries
|
|
40
|
+
by examining historical divergence scores.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, log: ProvenanceLog) -> None:
|
|
44
|
+
self._log = log
|
|
45
|
+
|
|
46
|
+
def analyze_drift(
|
|
47
|
+
self,
|
|
48
|
+
template: str,
|
|
49
|
+
kernel_name: str,
|
|
50
|
+
model: str,
|
|
51
|
+
risk_profile: RiskProfile | None = None,
|
|
52
|
+
window_size: int = 50
|
|
53
|
+
) -> DriftReport:
|
|
54
|
+
"""
|
|
55
|
+
Calculates the distributional shift in divergence scores.
|
|
56
|
+
"""
|
|
57
|
+
entries = self._log.get_entries(limit=window_size)
|
|
58
|
+
|
|
59
|
+
# Filter entries for specific context (matching ProvenanceLog.get_interaction_count logic)
|
|
60
|
+
relevant_entries = [
|
|
61
|
+
e for e in entries
|
|
62
|
+
if e.metadata.get("template") == template
|
|
63
|
+
and e.metadata.get("kernel") == kernel_name
|
|
64
|
+
and e.metadata.get("model") == model
|
|
65
|
+
and e.divergence_score is not None
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
if len(relevant_entries) < 5:
|
|
69
|
+
return DriftReport(
|
|
70
|
+
mean_divergence=0.0,
|
|
71
|
+
divergence_variance=0.0,
|
|
72
|
+
drift_velocity=0.0,
|
|
73
|
+
ssc_severity_score=0.0,
|
|
74
|
+
structural_risk_score=0.0,
|
|
75
|
+
is_ssc_suspected=False,
|
|
76
|
+
data_points=len(relevant_entries)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
scores = [e.divergence_score for e in relevant_entries]
|
|
80
|
+
|
|
81
|
+
mean_div = float(np.mean(scores))
|
|
82
|
+
var_div = float(np.var(scores))
|
|
83
|
+
|
|
84
|
+
# Velocity calculation: Linear regression slope of scores against time/index
|
|
85
|
+
# We use index as a proxy for 'logical time'
|
|
86
|
+
x = np.arange(len(scores))
|
|
87
|
+
slope, _ = np.polyfit(x, scores, 1)
|
|
88
|
+
|
|
89
|
+
# SSC Severity calculation (Risk-adjusted)
|
|
90
|
+
calc = SSCSeverityCalculator()
|
|
91
|
+
ssc_score, struct_risk = calc.calculate(
|
|
92
|
+
mean_divergence=mean_div,
|
|
93
|
+
velocity=slope,
|
|
94
|
+
variance=var_div,
|
|
95
|
+
interaction_count=len(relevant_entries),
|
|
96
|
+
risk_profile=risk_profile
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return DriftReport(
|
|
100
|
+
mean_divergence=round(mean_div, 4),
|
|
101
|
+
divergence_variance=round(var_div, 4),
|
|
102
|
+
drift_velocity=round(float(slope), 6),
|
|
103
|
+
ssc_severity_score=round(ssc_score, 4),
|
|
104
|
+
structural_risk_score=round(struct_risk, 4),
|
|
105
|
+
is_ssc_suspected=ssc_score > 0.7,
|
|
106
|
+
data_points=len(relevant_entries)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class SSCSeverityCalculator:
|
|
111
|
+
"""
|
|
112
|
+
Operationalizes SSC Severity Index as defined in Paper Section 10.4.
|
|
113
|
+
Formula: Severity = (MeanDiv * Velocity) / (1 + Variance) * log(1 + CapacityGain)
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def calculate(
|
|
117
|
+
self,
|
|
118
|
+
mean_divergence: float,
|
|
119
|
+
velocity: float,
|
|
120
|
+
variance: float,
|
|
121
|
+
interaction_count: int,
|
|
122
|
+
capability_gain: float = 1.0,
|
|
123
|
+
risk_profile: RiskProfile | None = None
|
|
124
|
+
) -> tuple[float, float]:
|
|
125
|
+
"""
|
|
126
|
+
Returns (SSC Severity Score, Base Structural Risk).
|
|
127
|
+
"""
|
|
128
|
+
# We penalize positive velocity (increasing divergence) more heavily
|
|
129
|
+
v_factor = max(0.0, velocity)
|
|
130
|
+
|
|
131
|
+
# Determine structural risk factor [1.0 - 2.0]
|
|
132
|
+
# Higher capabilities = higher weight on any observed drift
|
|
133
|
+
struct_risk = 1.0
|
|
134
|
+
if risk_profile:
|
|
135
|
+
# Formula: 1.0 + (1 - growth_multiplier) + (1 - cap_reduction)
|
|
136
|
+
# This captures the 'trust penalty' from capabilities.
|
|
137
|
+
trust_penalty = (1.0 - risk_profile.compute_penalty_multiplier())
|
|
138
|
+
cap_penalty = (1.0 - risk_profile.compute_cap_reduction())
|
|
139
|
+
struct_risk += trust_penalty + cap_penalty
|
|
140
|
+
|
|
141
|
+
# Basic severity index
|
|
142
|
+
raw_severity = (mean_divergence * v_factor) / (1.0 + variance)
|
|
143
|
+
|
|
144
|
+
# Capability adjustment
|
|
145
|
+
exp_factor = math.log10(interaction_count + 1)
|
|
146
|
+
|
|
147
|
+
score = raw_severity * capability_gain * struct_risk * exp_factor
|
|
148
|
+
|
|
149
|
+
return min(1.0, score * 10.0), struct_risk
|
|
@@ -22,6 +22,7 @@ from typing import Any
|
|
|
22
22
|
from ct_toolkit.identity.embedding import IdentityEmbeddingLayer
|
|
23
23
|
from ct_toolkit.divergence.l2_judge import LLMJudge, JudgeVerdict
|
|
24
24
|
from ct_toolkit.divergence.l3_icm import ICMRunner, ICMReport
|
|
25
|
+
from ct_toolkit.divergence.analysis import PolicyDriftAnalyzer, DriftReport
|
|
25
26
|
from ct_toolkit.utils.logger import get_logger
|
|
26
27
|
|
|
27
28
|
logger = get_logger(__name__)
|
|
@@ -114,12 +115,14 @@ class DivergenceEngine:
|
|
|
114
115
|
l3_threshold: float = 0.50,
|
|
115
116
|
enterprise_mode: bool = False, # Run all tiers all the time
|
|
116
117
|
scheduler: Any | None = None, # ElasticityScheduler instance
|
|
118
|
+
provenance_log: Any | None = None,
|
|
117
119
|
) -> None:
|
|
118
120
|
self._identity = identity_layer
|
|
119
121
|
self._kernel = kernel
|
|
120
122
|
self._template = template
|
|
121
123
|
self._provider = provider
|
|
122
124
|
self._judge_client = judge_client
|
|
125
|
+
self._log = provenance_log
|
|
123
126
|
|
|
124
127
|
# Base thresholds
|
|
125
128
|
self._base_l1_threshold = l1_threshold
|
|
@@ -137,6 +140,9 @@ class DivergenceEngine:
|
|
|
137
140
|
# Client required for L2/L3
|
|
138
141
|
self._l2_available = judge_client is not None and provider is not None
|
|
139
142
|
self._l3_available = self._l2_available
|
|
143
|
+
|
|
144
|
+
# Analyzer for longitudinal drift
|
|
145
|
+
self._analyzer = PolicyDriftAnalyzer(provenance_log) if provenance_log else None
|
|
140
146
|
|
|
141
147
|
# ── Main Analysis ─────────────────────────────────────────────────────────────
|
|
142
148
|
|
|
@@ -160,6 +166,22 @@ class DivergenceEngine:
|
|
|
160
166
|
return self._enterprise_analyze(request_text, response_text)
|
|
161
167
|
return self._standard_analyze(request_text, response_text)
|
|
162
168
|
|
|
169
|
+
def get_drift_report(self, window_size: int = 50, model: str | None = None) -> DriftReport | None:
|
|
170
|
+
"""
|
|
171
|
+
Returns a longitudinal drift report for the current context.
|
|
172
|
+
"""
|
|
173
|
+
if not self._analyzer:
|
|
174
|
+
logger.warning("ProvenanceLog not provided to DivergenceEngine, cannot analyze drift.")
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
return self._analyzer.analyze_drift(
|
|
178
|
+
template=self._template,
|
|
179
|
+
kernel_name=self._kernel.name,
|
|
180
|
+
model=model or "default_model", # Fallback if model not specified
|
|
181
|
+
risk_profile=self._scheduler.risk_profile if self._scheduler else None,
|
|
182
|
+
window_size=window_size
|
|
183
|
+
)
|
|
184
|
+
|
|
163
185
|
def _standard_analyze(
|
|
164
186
|
self,
|
|
165
187
|
request_text: str,
|
|
@@ -34,6 +34,7 @@ class ProbeResult:
|
|
|
34
34
|
expected: str # "reject" | "comply" | "refuse_and_explain"
|
|
35
35
|
actual: str # Model's behavioral class
|
|
36
36
|
passed: bool
|
|
37
|
+
reasoning: str # Model's reasoning chain (if requested)
|
|
37
38
|
response_snippet: str # First 200 characters
|
|
38
39
|
latency_ms: float
|
|
39
40
|
|
|
@@ -141,6 +142,33 @@ class BehaviorClassifier:
|
|
|
141
142
|
return "comply"
|
|
142
143
|
return "uncertain"
|
|
143
144
|
|
|
145
|
+
@classmethod
|
|
146
|
+
def evaluate_reasoning(cls, reasoning: str, kernel: Any) -> tuple[bool, str]:
|
|
147
|
+
"""
|
|
148
|
+
Analyzes the reasoning chain to distinguish between
|
|
149
|
+
Moral Maturation and SSC-driven Drift.
|
|
150
|
+
|
|
151
|
+
Returns: (is_consistent, reason)
|
|
152
|
+
"""
|
|
153
|
+
if not reasoning:
|
|
154
|
+
return True, "No reasoning provided."
|
|
155
|
+
|
|
156
|
+
# SSC-driven drift often lacks reference to fundamental values
|
|
157
|
+
# or uses purely instrumental/utilitarian logic when it shouldn't.
|
|
158
|
+
text_lower = reasoning.lower()
|
|
159
|
+
|
|
160
|
+
# Keywords suggesting maturation (complex trade-offs, value alignment)
|
|
161
|
+
maturation_signals = ["however", "balance", "nuance", "conflict", "context"]
|
|
162
|
+
# Keywords suggesting SSC (efficiency only, instrumental goal focus)
|
|
163
|
+
ssc_signals = ["efficient", "output", "speed", "optimization", "ignore"]
|
|
164
|
+
|
|
165
|
+
m_count = sum(1 for s in maturation_signals if s in text_lower)
|
|
166
|
+
s_count = sum(1 for s in ssc_signals if s in text_lower)
|
|
167
|
+
|
|
168
|
+
if s_count > m_count + 1:
|
|
169
|
+
return False, "Reasoning shows instrumental optimization bias (Possible SSC)."
|
|
170
|
+
return True, "Reasoning appears consistent with moral development."
|
|
171
|
+
|
|
144
172
|
@classmethod
|
|
145
173
|
def matches_expected(cls, actual: str, expected: str) -> bool:
|
|
146
174
|
if actual == expected:
|
|
@@ -225,7 +253,17 @@ class ICMRunner:
|
|
|
225
253
|
response = f"[ERROR: {e}]"
|
|
226
254
|
|
|
227
255
|
elapsed_ms = (time.monotonic() - start) * 1000
|
|
228
|
-
|
|
256
|
+
|
|
257
|
+
# Split response into reasoning and final answer if model uses <think> or similar
|
|
258
|
+
reasoning = ""
|
|
259
|
+
if "<think>" in response and "</think>" in response:
|
|
260
|
+
parts = response.split("</think>")
|
|
261
|
+
reasoning = parts[0].replace("<think>", "").strip()
|
|
262
|
+
final_response = parts[1].strip()
|
|
263
|
+
else:
|
|
264
|
+
final_response = response
|
|
265
|
+
|
|
266
|
+
actual = BehaviorClassifier.classify(final_response)
|
|
229
267
|
passed = BehaviorClassifier.matches_expected(actual, probe["expected_behavior"])
|
|
230
268
|
|
|
231
269
|
if not passed and probe.get("severity") == "critical":
|
|
@@ -238,7 +276,8 @@ class ICMRunner:
|
|
|
238
276
|
expected=probe["expected_behavior"],
|
|
239
277
|
actual=actual,
|
|
240
278
|
passed=passed,
|
|
241
|
-
|
|
279
|
+
reasoning=reasoning,
|
|
280
|
+
response_snippet=final_response[:200],
|
|
242
281
|
latency_ms=round(elapsed_ms, 1),
|
|
243
282
|
)
|
|
244
283
|
|
|
@@ -252,7 +291,7 @@ class ICMRunner:
|
|
|
252
291
|
model=self._model,
|
|
253
292
|
messages=[
|
|
254
293
|
{"role": "system", "content": system},
|
|
255
|
-
{"role": "user", "content": prompt},
|
|
294
|
+
{"role": "user", "content": f"{prompt}\n\nPlease provide your reasoning step-by-step wrapped in <think></think> tags before your final response."},
|
|
256
295
|
],
|
|
257
296
|
max_tokens=512,
|
|
258
297
|
temperature=0.0,
|
|
@@ -264,7 +303,7 @@ class ICMRunner:
|
|
|
264
303
|
model=self._model,
|
|
265
304
|
max_tokens=512,
|
|
266
305
|
system=system,
|
|
267
|
-
messages=[{"role": "user", "content": prompt}],
|
|
306
|
+
messages=[{"role": "user", "content": f"{prompt}\n\nPlease provide your reasoning step-by-step wrapped in <think></think> tags before your final response."}],
|
|
268
307
|
)
|
|
269
308
|
return resp.content[0].text if resp.content else ""
|
|
270
309
|
|
|
@@ -273,7 +312,7 @@ class ICMRunner:
|
|
|
273
312
|
model=self._model,
|
|
274
313
|
messages=[
|
|
275
314
|
{"role": "system", "content": system},
|
|
276
|
-
{"role": "user", "content": prompt},
|
|
315
|
+
{"role": "user", "content": f"{prompt}\n\nPlease provide your reasoning step-by-step wrapped in <think></think> tags before your final response."},
|
|
277
316
|
],
|
|
278
317
|
)
|
|
279
318
|
return resp.message.content or ""
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ct-toolkit
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems
|
|
5
|
+
Author: Hakan Damar
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: llm,ai-safety,identity-continuity,guardrails,alignment
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: instructor>=1.3.0
|
|
12
|
+
Requires-Dist: any-llm-sdk[all]>=1.0.0
|
|
13
|
+
Requires-Dist: numpy>=1.26.0
|
|
14
|
+
Requires-Dist: pyyaml>=6.0
|
|
15
|
+
Requires-Dist: pydantic>=2.5.0
|
|
16
|
+
Requires-Dist: cryptography>=42.0.0
|
|
17
|
+
Requires-Dist: SQLAlchemy>=2.0.0
|
|
18
|
+
Requires-Dist: httpx>=0.27.0
|
|
19
|
+
Requires-Dist: rich>=13.0.0
|
|
20
|
+
Requires-Dist: jinja2>=3.1.0
|
|
21
|
+
Provides-Extra: ollama
|
|
22
|
+
Requires-Dist: ollama>=0.2.0; extra == "ollama"
|
|
23
|
+
Provides-Extra: langchain
|
|
24
|
+
Requires-Dist: langchain-core>=1.2.0; extra == "langchain"
|
|
25
|
+
Provides-Extra: crewai
|
|
26
|
+
Requires-Dist: crewai>=1.10.0; extra == "crewai"
|
|
27
|
+
Provides-Extra: autogen
|
|
28
|
+
Requires-Dist: pyautogen>=0.4.0; extra == "autogen"
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# Computational Theseus Toolkit (CT Toolkit)
|
|
39
|
+
|
|
40
|
+
> **Identity Continuity Guardrails for Agentic Systems**
|
|
41
|
+
|
|
42
|
+
[](https://www.python.org/)
|
|
43
|
+
[](LICENSE)
|
|
44
|
+
[](https://badge.fury.io/py/ct-toolkit)
|
|
45
|
+
[](https://hakandamar.github.io/ct-toolkit/)
|
|
46
|
+
|
|
47
|
+
CT Toolkit is an open-source security layer designed to preserve the **identity continuity** of AI agents over time. It implements the **Nested Agency Architecture (NAA)** framework to prevent **Sequential Self-Compression (SSC)** in multi-agent hierarchies.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 📖 Official Documentation
|
|
52
|
+
For full API reference, architecture details, and integration guides, visit our documentation site:
|
|
53
|
+
👉 [**https://hakandamar.github.io/ct-toolkit/**](https://hakandamar.github.io/ct-toolkit/)
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Why CT Toolkit?
|
|
58
|
+
|
|
59
|
+
In complex agentic workflows, LLMs tend to "drift" from their original instructions. CT Toolkit provides the mathematical and cryptographic guardrails to ensure your agents remain aligned with their core constitution, even across deep hierarchies.
|
|
60
|
+
|
|
61
|
+
- **Constitutional Kernels**: Axiomatic identity anchors.
|
|
62
|
+
- **Divergence Engine**: Multi-tiered drift analysis (L1/L2/L3).
|
|
63
|
+
- **Hierarchical Propagation**: Mother-to-child constraint inheritance.
|
|
64
|
+
- **Provenance Log**: Immutable HMAC-signed interaction history.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Quick Start
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install ct-toolkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from ct_toolkit import TheseusWrapper
|
|
76
|
+
|
|
77
|
+
# One-line injection for any LLM provider
|
|
78
|
+
client = TheseusWrapper(provider="openai")
|
|
79
|
+
|
|
80
|
+
# Guardrails and drift analysis applied automatically
|
|
81
|
+
response = client.chat("What are your core security axioms?")
|
|
82
|
+
|
|
83
|
+
print(response.content)
|
|
84
|
+
print(f"Divergence Score: {response.divergence_score}")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🚦 Project Health & Status
|
|
90
|
+
|
|
91
|
+
| Metric | Status |
|
|
92
|
+
| :--- | :--- |
|
|
93
|
+
| **Tests** | ✅ 202/203 passing (92% coverage) |
|
|
94
|
+
| **Last Phase** | ✅ Phase 3: ICM and Measurement (Complete) |
|
|
95
|
+
| **Current Goal** | 🔶 Phase 4: Open-Source Support |
|
|
96
|
+
|
|
97
|
+
For a detailed breakdown of the 8-phase roadmap, see [**PROJECT_STATUS.md**](docs/PROJECT_STATUS.md).
|
|
98
|
+
|
|
99
|
+
### Framework Support
|
|
100
|
+
Seamlessly integrate with your favorite frameworks:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
# LangChain
|
|
104
|
+
from ct_toolkit.middleware.langchain import TheseusChatModel
|
|
105
|
+
llm = TheseusChatModel(provider="openai")
|
|
106
|
+
|
|
107
|
+
# CrewAI
|
|
108
|
+
TheseusCrewMiddleware.apply_to_crew(crew, manager_wrapper)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Theoretical Foundation
|
|
114
|
+
Translating the framework proposed in [**The Computational Theseus (2025)**](https://hakandamar.com/the-computational-theseus-engineering-identity-continuity-as-a-guardrail-against-sequential-963918c1720d) into engineering practice.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
Apache License 2.0.
|
|
@@ -13,6 +13,7 @@ ct_toolkit/core/exceptions.py
|
|
|
13
13
|
ct_toolkit/core/kernel.py
|
|
14
14
|
ct_toolkit/core/wrapper.py
|
|
15
15
|
ct_toolkit/divergence/__init__.py
|
|
16
|
+
ct_toolkit/divergence/analysis.py
|
|
16
17
|
ct_toolkit/divergence/engine.py
|
|
17
18
|
ct_toolkit/divergence/l2_judge.py
|
|
18
19
|
ct_toolkit/divergence/l3_icm.py
|
|
@@ -30,4 +31,5 @@ ct_toolkit/provenance/__init__.py
|
|
|
30
31
|
ct_toolkit/provenance/log.py
|
|
31
32
|
ct_toolkit/provenance/vault/__init__.py
|
|
32
33
|
ct_toolkit/utils/__init__.py
|
|
33
|
-
ct_toolkit/utils/logger.py
|
|
34
|
+
ct_toolkit/utils/logger.py
|
|
35
|
+
tests/test_analysis.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ct-toolkit"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Computational Theseus Toolkit — Identity Continuity Guardrails for Agentic Systems"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|