agent-killswitch 0.1.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.
- agent_killswitch-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
- agent_killswitch-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +54 -0
- agent_killswitch-0.1.0/.github/workflows/ci.yml +71 -0
- agent_killswitch-0.1.0/.github/workflows/release.yml +68 -0
- agent_killswitch-0.1.0/.gitignore +46 -0
- agent_killswitch-0.1.0/.ruff.toml +55 -0
- agent_killswitch-0.1.0/CHANGELOG.md +29 -0
- agent_killswitch-0.1.0/CONTRIBUTING.md +117 -0
- agent_killswitch-0.1.0/LICENSE +190 -0
- agent_killswitch-0.1.0/Makefile +54 -0
- agent_killswitch-0.1.0/PKG-INFO +392 -0
- agent_killswitch-0.1.0/README.md +340 -0
- agent_killswitch-0.1.0/SECURITY.md +52 -0
- agent_killswitch-0.1.0/benchmarks/bench_kill_latency.py +101 -0
- agent_killswitch-0.1.0/examples/asyncio_agents.py +74 -0
- agent_killswitch-0.1.0/examples/basic_usage.py +75 -0
- agent_killswitch-0.1.0/examples/budget_kill_trigger.py +74 -0
- agent_killswitch-0.1.0/examples/circuit_breaker_pattern.py +94 -0
- agent_killswitch-0.1.0/examples/heartbeat_monitor.py +76 -0
- agent_killswitch-0.1.0/examples/langchain_integration.py +59 -0
- agent_killswitch-0.1.0/noxfile.py +64 -0
- agent_killswitch-0.1.0/pyproject.toml +136 -0
- agent_killswitch-0.1.0/src/agent_killswitch/__init__.py +76 -0
- agent_killswitch-0.1.0/src/agent_killswitch/_version.py +5 -0
- agent_killswitch-0.1.0/src/agent_killswitch/backends/__init__.py +21 -0
- agent_killswitch-0.1.0/src/agent_killswitch/backends/base.py +95 -0
- agent_killswitch-0.1.0/src/agent_killswitch/backends/memory.py +120 -0
- agent_killswitch-0.1.0/src/agent_killswitch/backends/redis.py +230 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/__init__.py +36 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/budget_kill.py +281 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/cascading.py +280 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/circuit_breaker.py +323 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/enums.py +112 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/heartbeat.py +313 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/killswitch.py +581 -0
- agent_killswitch-0.1.0/src/agent_killswitch/core/models.py +173 -0
- agent_killswitch-0.1.0/src/agent_killswitch/decorators.py +302 -0
- agent_killswitch-0.1.0/src/agent_killswitch/integrations/__init__.py +17 -0
- agent_killswitch-0.1.0/src/agent_killswitch/integrations/asyncio_tasks.py +211 -0
- agent_killswitch-0.1.0/src/agent_killswitch/integrations/crewai.py +151 -0
- agent_killswitch-0.1.0/src/agent_killswitch/integrations/langchain.py +135 -0
- agent_killswitch-0.1.0/src/agent_killswitch/integrations/langgraph.py +143 -0
- agent_killswitch-0.1.0/src/agent_killswitch/integrations/openai_agents.py +151 -0
- agent_killswitch-0.1.0/src/agent_killswitch/py.typed +0 -0
- agent_killswitch-0.1.0/tests/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/chaos/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/chaos/test_backend_failure.py +129 -0
- agent_killswitch-0.1.0/tests/chaos/test_concurrent_kills.py +135 -0
- agent_killswitch-0.1.0/tests/chaos/test_network_partition.py +126 -0
- agent_killswitch-0.1.0/tests/conftest.py +63 -0
- agent_killswitch-0.1.0/tests/e2e/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/e2e/test_cascading_termination.py +104 -0
- agent_killswitch-0.1.0/tests/e2e/test_full_kill_flow.py +142 -0
- agent_killswitch-0.1.0/tests/e2e/test_heartbeat_recovery.py +109 -0
- agent_killswitch-0.1.0/tests/integration/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/integration/test_asyncio_integration.py +129 -0
- agent_killswitch-0.1.0/tests/integration/test_framework_integrations.py +176 -0
- agent_killswitch-0.1.0/tests/integration/test_langchain_integration.py +96 -0
- agent_killswitch-0.1.0/tests/integration/test_redis_backend.py +101 -0
- agent_killswitch-0.1.0/tests/performance/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/performance/test_heartbeat_overhead.py +74 -0
- agent_killswitch-0.1.0/tests/performance/test_kill_latency.py +110 -0
- agent_killswitch-0.1.0/tests/security/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/security/test_bypass_prevention.py +117 -0
- agent_killswitch-0.1.0/tests/security/test_unauthorized_kill.py +94 -0
- agent_killswitch-0.1.0/tests/unit/__init__.py +0 -0
- agent_killswitch-0.1.0/tests/unit/test_backends.py +118 -0
- agent_killswitch-0.1.0/tests/unit/test_budget_kill.py +161 -0
- agent_killswitch-0.1.0/tests/unit/test_cascading.py +132 -0
- agent_killswitch-0.1.0/tests/unit/test_circuit_breaker.py +221 -0
- agent_killswitch-0.1.0/tests/unit/test_decorators.py +189 -0
- agent_killswitch-0.1.0/tests/unit/test_heartbeat.py +168 -0
- agent_killswitch-0.1.0/tests/unit/test_killswitch.py +312 -0
- agent_killswitch-0.1.0/tests/unit/test_models.py +196 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug in agent-killswitch
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for reporting a bug! Please fill out the details below.
|
|
10
|
+
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: description
|
|
13
|
+
attributes:
|
|
14
|
+
label: Description
|
|
15
|
+
description: What happened? What did you expect to happen?
|
|
16
|
+
placeholder: Describe the bug...
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: reproduction
|
|
22
|
+
attributes:
|
|
23
|
+
label: Steps to Reproduce
|
|
24
|
+
description: Minimal code to reproduce the issue.
|
|
25
|
+
placeholder: |
|
|
26
|
+
```python
|
|
27
|
+
from agent_killswitch import KillSwitch
|
|
28
|
+
ks = KillSwitch()
|
|
29
|
+
# ...
|
|
30
|
+
```
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
|
|
34
|
+
- type: input
|
|
35
|
+
id: version
|
|
36
|
+
attributes:
|
|
37
|
+
label: Version
|
|
38
|
+
description: What version of agent-killswitch are you using?
|
|
39
|
+
placeholder: "0.1.0"
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
|
|
43
|
+
- type: input
|
|
44
|
+
id: python-version
|
|
45
|
+
attributes:
|
|
46
|
+
label: Python Version
|
|
47
|
+
placeholder: "3.12"
|
|
48
|
+
validations:
|
|
49
|
+
required: true
|
|
50
|
+
|
|
51
|
+
- type: dropdown
|
|
52
|
+
id: backend
|
|
53
|
+
attributes:
|
|
54
|
+
label: Backend
|
|
55
|
+
options:
|
|
56
|
+
- InMemoryBackend (default)
|
|
57
|
+
- RedisBackend
|
|
58
|
+
- Custom backend
|
|
59
|
+
validations:
|
|
60
|
+
required: true
|
|
61
|
+
|
|
62
|
+
- type: textarea
|
|
63
|
+
id: logs
|
|
64
|
+
attributes:
|
|
65
|
+
label: Relevant Logs
|
|
66
|
+
description: Any error messages or stack traces.
|
|
67
|
+
render: shell
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature for agent-killswitch
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for suggesting a feature! Please describe what you'd like.
|
|
10
|
+
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: problem
|
|
13
|
+
attributes:
|
|
14
|
+
label: Problem
|
|
15
|
+
description: What problem does this feature solve?
|
|
16
|
+
placeholder: "I'm trying to... but there's no way to..."
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: solution
|
|
22
|
+
attributes:
|
|
23
|
+
label: Proposed Solution
|
|
24
|
+
description: How would you like this to work?
|
|
25
|
+
placeholder: "It would be great if..."
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: alternatives
|
|
31
|
+
attributes:
|
|
32
|
+
label: Alternatives Considered
|
|
33
|
+
description: Any alternative solutions you've considered?
|
|
34
|
+
|
|
35
|
+
- type: dropdown
|
|
36
|
+
id: component
|
|
37
|
+
attributes:
|
|
38
|
+
label: Component
|
|
39
|
+
options:
|
|
40
|
+
- Core KillSwitch
|
|
41
|
+
- Heartbeat Monitor
|
|
42
|
+
- Circuit Breaker
|
|
43
|
+
- Budget Kill
|
|
44
|
+
- Cascading Termination
|
|
45
|
+
- Backends
|
|
46
|
+
- Decorators
|
|
47
|
+
- LangChain Integration
|
|
48
|
+
- LangGraph Integration
|
|
49
|
+
- CrewAI Integration
|
|
50
|
+
- OpenAI Agents Integration
|
|
51
|
+
- asyncio Integration
|
|
52
|
+
- Other
|
|
53
|
+
validations:
|
|
54
|
+
required: true
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
|
|
29
|
+
- name: Lint
|
|
30
|
+
run: ruff check src/ tests/
|
|
31
|
+
|
|
32
|
+
- name: Format check
|
|
33
|
+
run: ruff format --check src/ tests/
|
|
34
|
+
|
|
35
|
+
- name: Unit tests
|
|
36
|
+
run: pytest tests/unit/ -v --timeout=30
|
|
37
|
+
|
|
38
|
+
- name: E2E tests
|
|
39
|
+
run: pytest tests/e2e/ -v --timeout=60
|
|
40
|
+
|
|
41
|
+
- name: Chaos tests
|
|
42
|
+
run: pytest tests/chaos/ -v --timeout=30
|
|
43
|
+
|
|
44
|
+
- name: Performance tests
|
|
45
|
+
run: pytest tests/performance/ -v --timeout=60
|
|
46
|
+
|
|
47
|
+
- name: Security tests
|
|
48
|
+
run: pytest tests/security/ -v --timeout=30
|
|
49
|
+
|
|
50
|
+
- name: Coverage
|
|
51
|
+
if: matrix.python-version == '3.12'
|
|
52
|
+
run: |
|
|
53
|
+
pytest tests/ -v --cov=agent_killswitch --cov-report=xml --timeout=60
|
|
54
|
+
|
|
55
|
+
- name: Upload coverage
|
|
56
|
+
if: matrix.python-version == '3.12'
|
|
57
|
+
uses: codecov/codecov-action@v4
|
|
58
|
+
with:
|
|
59
|
+
file: ./coverage.xml
|
|
60
|
+
fail_ci_if_error: false
|
|
61
|
+
|
|
62
|
+
type-check:
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
- uses: actions/setup-python@v5
|
|
67
|
+
with:
|
|
68
|
+
python-version: "3.12"
|
|
69
|
+
- run: |
|
|
70
|
+
pip install -e ".[dev]"
|
|
71
|
+
mypy src/agent_killswitch/
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: pip install build
|
|
24
|
+
|
|
25
|
+
- name: Build
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Upload artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish-pypi:
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
environment: pypi
|
|
38
|
+
permissions:
|
|
39
|
+
id-token: write
|
|
40
|
+
steps:
|
|
41
|
+
- name: Download artifacts
|
|
42
|
+
uses: actions/download-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
- name: Publish to PyPI
|
|
48
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
49
|
+
|
|
50
|
+
github-release:
|
|
51
|
+
needs: build
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
permissions:
|
|
54
|
+
contents: write
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: Download artifacts
|
|
59
|
+
uses: actions/download-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: dist
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Create GitHub Release
|
|
65
|
+
uses: softprops/action-gh-release@v2
|
|
66
|
+
with:
|
|
67
|
+
files: dist/*
|
|
68
|
+
generate_release_notes: true
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.whl
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Testing
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.benchmarks/
|
|
20
|
+
htmlcov/
|
|
21
|
+
.coverage
|
|
22
|
+
.coverage.*
|
|
23
|
+
coverage.xml
|
|
24
|
+
*.cover
|
|
25
|
+
|
|
26
|
+
# Type checking
|
|
27
|
+
.mypy_cache/
|
|
28
|
+
|
|
29
|
+
# Linting
|
|
30
|
+
.ruff_cache/
|
|
31
|
+
|
|
32
|
+
# IDE
|
|
33
|
+
.vscode/
|
|
34
|
+
.idea/
|
|
35
|
+
*.swp
|
|
36
|
+
*.swo
|
|
37
|
+
*~
|
|
38
|
+
|
|
39
|
+
# OS
|
|
40
|
+
.DS_Store
|
|
41
|
+
Thumbs.db
|
|
42
|
+
|
|
43
|
+
# Environment
|
|
44
|
+
.env
|
|
45
|
+
.env.local
|
|
46
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Ruff configuration for agent-killswitch
|
|
2
|
+
target-version = "py310"
|
|
3
|
+
line-length = 100
|
|
4
|
+
|
|
5
|
+
[lint]
|
|
6
|
+
select = [
|
|
7
|
+
"E", # pycodestyle errors
|
|
8
|
+
"W", # pycodestyle warnings
|
|
9
|
+
"F", # pyflakes
|
|
10
|
+
"I", # isort
|
|
11
|
+
"N", # pep8-naming
|
|
12
|
+
"UP", # pyupgrade
|
|
13
|
+
"B", # flake8-bugbear
|
|
14
|
+
"SIM", # flake8-simplify
|
|
15
|
+
"TCH", # flake8-type-checking
|
|
16
|
+
"RUF", # Ruff-specific rules
|
|
17
|
+
]
|
|
18
|
+
ignore = [
|
|
19
|
+
"E501", # line too long (handled by formatter)
|
|
20
|
+
"B008", # do not perform function calls in argument defaults
|
|
21
|
+
"SIM108", # use ternary operator
|
|
22
|
+
"UP007", # use X | Y for union types (we support 3.10)
|
|
23
|
+
|
|
24
|
+
# --- Deliberate, documented exceptions ---------------------------------
|
|
25
|
+
# N818 "exception name should end in Error": `KillSwitchTriggered` and
|
|
26
|
+
# `CircuitBreakerOpen` are CONTROL-FLOW SIGNALS, not failures — the same
|
|
27
|
+
# category as the standard library's StopIteration, KeyboardInterrupt and
|
|
28
|
+
# SystemExit, none of which carry the suffix. `except KillSwitchTriggered:`
|
|
29
|
+
# states the intent exactly; renaming would make the API less clear.
|
|
30
|
+
"N818",
|
|
31
|
+
|
|
32
|
+
# TC001/TC002/TC003 "move this import into a TYPE_CHECKING block": this
|
|
33
|
+
# library has ZERO required runtime dependencies and imports only from the
|
|
34
|
+
# standard library, so guarding those imports saves no install time and no
|
|
35
|
+
# import time. It would only add a conditional block and quoted annotations
|
|
36
|
+
# to every module — cost without benefit here.
|
|
37
|
+
"TC001",
|
|
38
|
+
"TC002",
|
|
39
|
+
"TC003",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[lint.per-file-ignores]
|
|
43
|
+
# RUF006 wants every asyncio task reference held in a long-lived collection. In these
|
|
44
|
+
# tests the task is created, awaited-through and consumed inside a single coroutine, so
|
|
45
|
+
# the local binding already keeps it alive for exactly as long as it must exist. The
|
|
46
|
+
# library code itself does hold real references - see integrations/asyncio_tasks.py.
|
|
47
|
+
"tests/**" = ["RUF006"]
|
|
48
|
+
|
|
49
|
+
[lint.isort]
|
|
50
|
+
known-first-party = ["agent_killswitch"]
|
|
51
|
+
|
|
52
|
+
[format]
|
|
53
|
+
quote-style = "double"
|
|
54
|
+
indent-style = "space"
|
|
55
|
+
docstring-code-format = true
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-09-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Core `KillSwitch` class with tiered levels (PAUSE/STOP/KILL) and scoped targets (GLOBAL/CREW/AGENT/TASK)
|
|
13
|
+
- `HeartbeatMonitor` for tracking agent health with configurable intervals and miss thresholds
|
|
14
|
+
- `CircuitBreaker` pattern with CLOSED/OPEN/HALF_OPEN states
|
|
15
|
+
- `BudgetKillTrigger` for automatic kills when cost budgets are exceeded
|
|
16
|
+
- `CascadingTerminator` for parent-child agent hierarchy termination
|
|
17
|
+
- `InMemoryBackend` (zero dependencies, default)
|
|
18
|
+
- `RedisBackend` (optional, for distributed systems)
|
|
19
|
+
- Decorators: `@killswitch_protected`, `@with_heartbeat`, `@circuit_breaker`
|
|
20
|
+
- LangChain integration (callback handler)
|
|
21
|
+
- LangGraph integration (node and conditional edge)
|
|
22
|
+
- CrewAI integration (pre-action hook)
|
|
23
|
+
- OpenAI Agents SDK integration (guardrail)
|
|
24
|
+
- asyncio integration (task group cancellation)
|
|
25
|
+
- Fail-closed safety: backend failures default to KILLED state
|
|
26
|
+
- Full audit trail for all kill events
|
|
27
|
+
- Thread-safe and async-safe implementations
|
|
28
|
+
- Type hints on all public APIs
|
|
29
|
+
- py.typed marker for PEP 561
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Contributing to agent-killswitch
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to agent-killswitch! This document
|
|
4
|
+
provides guidelines and information for contributors.
|
|
5
|
+
|
|
6
|
+
## Development Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Clone the repository
|
|
10
|
+
git clone https://github.com/veerarakesh56/agent-killswitch.git
|
|
11
|
+
cd agent-killswitch
|
|
12
|
+
|
|
13
|
+
# Install in development mode
|
|
14
|
+
pip install -e ".[dev,all]"
|
|
15
|
+
|
|
16
|
+
# Run tests
|
|
17
|
+
make test
|
|
18
|
+
|
|
19
|
+
# Run linting
|
|
20
|
+
make lint
|
|
21
|
+
|
|
22
|
+
# Run type checking
|
|
23
|
+
make typecheck
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Running Tests
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# All tests
|
|
30
|
+
make test
|
|
31
|
+
|
|
32
|
+
# Specific test suites
|
|
33
|
+
make test-unit # Unit tests
|
|
34
|
+
make test-integration # Integration tests
|
|
35
|
+
make test-e2e # End-to-end tests
|
|
36
|
+
make test-chaos # Chaos/fault-injection tests
|
|
37
|
+
make test-perf # Performance tests
|
|
38
|
+
make test-security # Security tests
|
|
39
|
+
|
|
40
|
+
# With coverage
|
|
41
|
+
make coverage
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Code Quality
|
|
45
|
+
|
|
46
|
+
We use:
|
|
47
|
+
- **ruff** for linting and formatting
|
|
48
|
+
- **mypy** for type checking
|
|
49
|
+
- **pytest** for testing
|
|
50
|
+
|
|
51
|
+
Before submitting a PR:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
make lint # Check for linting errors
|
|
55
|
+
make format # Auto-format code
|
|
56
|
+
make typecheck # Run type checker
|
|
57
|
+
make test # Run all tests
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Architecture Principles
|
|
61
|
+
|
|
62
|
+
1. **Zero required dependencies**: Core functionality must work with Python stdlib only
|
|
63
|
+
2. **Fail-closed**: When in doubt, default to the safe state (KILLED)
|
|
64
|
+
3. **Thread-safe**: All public APIs must be safe for concurrent access
|
|
65
|
+
4. **Outside the reasoning path**: Kill switch operates at infrastructure level
|
|
66
|
+
5. **No TTL**: Kill switches require explicit deactivation
|
|
67
|
+
6. **Audit everything**: Every state change must be logged
|
|
68
|
+
|
|
69
|
+
## Adding a New Backend
|
|
70
|
+
|
|
71
|
+
1. Create a new file in `src/agent_killswitch/backends/`
|
|
72
|
+
2. Implement the `KillSwitchBackend` protocol from `backends/base.py`
|
|
73
|
+
3. Add tests in `tests/unit/test_backends.py`
|
|
74
|
+
4. Document in README.md
|
|
75
|
+
|
|
76
|
+
## Adding a New Integration
|
|
77
|
+
|
|
78
|
+
1. Create a new file in `src/agent_killswitch/integrations/`
|
|
79
|
+
2. The integration should be a thin adapter (minimal code)
|
|
80
|
+
3. Framework dependency should be optional (import in function, not at module level)
|
|
81
|
+
4. Add the framework to `[project.optional-dependencies]` in `pyproject.toml`
|
|
82
|
+
5. Add tests in `tests/integration/`
|
|
83
|
+
6. Add an example in `examples/`
|
|
84
|
+
|
|
85
|
+
## Pull Request Process
|
|
86
|
+
|
|
87
|
+
1. Fork the repository
|
|
88
|
+
2. Create a feature branch (`git checkout -b feature/my-feature`)
|
|
89
|
+
3. Make your changes
|
|
90
|
+
4. Run all checks (`make lint && make typecheck && make test`)
|
|
91
|
+
5. Commit with a descriptive message
|
|
92
|
+
6. Push to your fork
|
|
93
|
+
7. Open a Pull Request
|
|
94
|
+
|
|
95
|
+
## Commit Message Format
|
|
96
|
+
|
|
97
|
+
We use conventional commits:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
feat: add new backend for DynamoDB
|
|
101
|
+
fix: correct race condition in heartbeat monitor
|
|
102
|
+
docs: update README with new examples
|
|
103
|
+
test: add chaos tests for network partition
|
|
104
|
+
refactor: simplify circuit breaker state machine
|
|
105
|
+
chore: update CI to test Python 3.13
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Reporting Issues
|
|
109
|
+
|
|
110
|
+
Use the issue templates on GitHub:
|
|
111
|
+
- **Bug Report**: For bugs and unexpected behavior
|
|
112
|
+
- **Feature Request**: For new features and enhancements
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
By contributing, you agree that your contributions will be licensed under
|
|
117
|
+
the Apache License 2.0.
|