jhcontext 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.
- jhcontext-0.2.0/.github/workflows/publish.yml +113 -0
- jhcontext-0.2.0/LICENSE +3 -0
- jhcontext-0.2.0/PKG-INFO +248 -0
- jhcontext-0.2.0/README.md +202 -0
- jhcontext-0.2.0/SESSION_CONTINUE.md +86 -0
- jhcontext-0.2.0/cli.py +24 -0
- jhcontext-0.2.0/example_envelope.json +69 -0
- jhcontext-0.2.0/jhcontext/__init__.py +60 -0
- jhcontext-0.2.0/jhcontext/audit.py +207 -0
- jhcontext-0.2.0/jhcontext/builder.py +153 -0
- jhcontext-0.2.0/jhcontext/canonicalize.py +5 -0
- jhcontext-0.2.0/jhcontext/cli.py +80 -0
- jhcontext-0.2.0/jhcontext/client/__init__.py +4 -0
- jhcontext-0.2.0/jhcontext/client/api_client.py +133 -0
- jhcontext-0.2.0/jhcontext/client/config.py +11 -0
- jhcontext-0.2.0/jhcontext/crypto.py +106 -0
- jhcontext-0.2.0/jhcontext/envelope.py +37 -0
- jhcontext-0.2.0/jhcontext/integrations/__init__.py +0 -0
- jhcontext-0.2.0/jhcontext/models.py +141 -0
- jhcontext-0.2.0/jhcontext/prov.py +225 -0
- jhcontext-0.2.0/jhcontext/semantics.py +59 -0
- jhcontext-0.2.0/jhcontext/server/__init__.py +1 -0
- jhcontext-0.2.0/jhcontext/server/app.py +51 -0
- jhcontext-0.2.0/jhcontext/server/auth/__init__.py +0 -0
- jhcontext-0.2.0/jhcontext/server/mcp_server.py +162 -0
- jhcontext-0.2.0/jhcontext/server/routes/__init__.py +0 -0
- jhcontext-0.2.0/jhcontext/server/routes/artifacts.py +55 -0
- jhcontext-0.2.0/jhcontext/server/routes/compliance.py +56 -0
- jhcontext-0.2.0/jhcontext/server/routes/decisions.py +41 -0
- jhcontext-0.2.0/jhcontext/server/routes/envelopes.py +47 -0
- jhcontext-0.2.0/jhcontext/server/routes/provenance.py +64 -0
- jhcontext-0.2.0/jhcontext/server/storage/__init__.py +26 -0
- jhcontext-0.2.0/jhcontext/server/storage/sqlite.py +236 -0
- jhcontext-0.2.0/jhcontext/utils.py +19 -0
- jhcontext-0.2.0/jhcontext/validate.py +8 -0
- jhcontext-0.2.0/pyproject.toml +63 -0
- jhcontext-0.2.0/tests/test_audit.py +230 -0
- jhcontext-0.2.0/tests/test_builder.py +173 -0
- jhcontext-0.2.0/tests/test_canonicalize.py +28 -0
- jhcontext-0.2.0/tests/test_crypto.py +116 -0
- jhcontext-0.2.0/tests/test_example.py +16 -0
- jhcontext-0.2.0/tests/test_models.py +188 -0
- jhcontext-0.2.0/tests/test_prov.py +174 -0
- jhcontext-0.2.0/tests/test_semantics.py +71 -0
- jhcontext-0.2.0/tests/test_server.py +78 -0
- jhcontext-0.2.0/tests/test_storage.py +147 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
name: Build and Publish Python package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- 'v*' # tags like v0.1.0 will trigger publish -> PyPI
|
|
9
|
+
pull_request:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
repository:
|
|
15
|
+
description: 'target repository (testpypi or pypi)'
|
|
16
|
+
required: true
|
|
17
|
+
default: 'testpypi'
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
name: Run tests & build
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout
|
|
25
|
+
uses: actions/checkout@v4
|
|
26
|
+
|
|
27
|
+
- name: Set up Python
|
|
28
|
+
uses: actions/setup-python@v4
|
|
29
|
+
with:
|
|
30
|
+
python-version: '3.10'
|
|
31
|
+
|
|
32
|
+
- name: Install build/test deps
|
|
33
|
+
run: |
|
|
34
|
+
python -m pip install --upgrade pip build wheel pytest
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: |
|
|
38
|
+
pytest -q || true # keep build job non-fatal if you use tests later
|
|
39
|
+
|
|
40
|
+
- name: Build distributions
|
|
41
|
+
run: |
|
|
42
|
+
python -m build --sdist --wheel
|
|
43
|
+
|
|
44
|
+
- name: Upload artifact (for later jobs)
|
|
45
|
+
uses: actions/upload-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: dist-artifacts
|
|
48
|
+
path: dist/*
|
|
49
|
+
|
|
50
|
+
publish:
|
|
51
|
+
name: Publish to PyPI / TestPyPI
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/v')
|
|
55
|
+
steps:
|
|
56
|
+
- name: Checkout
|
|
57
|
+
uses: actions/checkout@v4
|
|
58
|
+
|
|
59
|
+
- name: Download built artifacts
|
|
60
|
+
uses: actions/download-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: dist-artifacts
|
|
63
|
+
path: dist
|
|
64
|
+
|
|
65
|
+
- name: Set up Python
|
|
66
|
+
uses: actions/setup-python@v4
|
|
67
|
+
with:
|
|
68
|
+
python-version: '3.10'
|
|
69
|
+
|
|
70
|
+
- name: Install upload tools
|
|
71
|
+
run: |
|
|
72
|
+
python -m pip install --upgrade pip
|
|
73
|
+
pip install build twine
|
|
74
|
+
|
|
75
|
+
- name: Determine target repository and token
|
|
76
|
+
id: repoinfo
|
|
77
|
+
run: |
|
|
78
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
79
|
+
REPO="${{ github.event.inputs.repository }}"
|
|
80
|
+
else
|
|
81
|
+
# if triggered by tag push, default to pypi
|
|
82
|
+
REPO="pypi"
|
|
83
|
+
fi
|
|
84
|
+
echo "repository=${REPO}" >> $GITHUB_OUTPUT
|
|
85
|
+
if [ "${REPO}" = "testpypi" ]; then
|
|
86
|
+
echo "url=https://test.pypi.org/legacy/" >> $GITHUB_OUTPUT
|
|
87
|
+
echo "token_secret=TEST_PYPI_API_TOKEN" >> $GITHUB_OUTPUT
|
|
88
|
+
else
|
|
89
|
+
echo "url=https://upload.pypi.org/legacy/" >> $GITHUB_OUTPUT
|
|
90
|
+
echo "token_secret=PYPI_API_TOKEN" >> $GITHUB_OUTPUT
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
- name: Publish to chosen PyPI
|
|
94
|
+
env:
|
|
95
|
+
REPO_URL: ${{ steps.repoinfo.outputs.url }}
|
|
96
|
+
run: |
|
|
97
|
+
# choose token from secrets
|
|
98
|
+
if [ "${{ steps.repoinfo.outputs.token_secret }}" = "TEST_PYPI_API_TOKEN" ]; then
|
|
99
|
+
TOKEN="${{ secrets.TEST_PYPI_API_TOKEN }}"
|
|
100
|
+
else
|
|
101
|
+
TOKEN="${{ secrets.PYPI_API_TOKEN }}"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
if [ -z "$TOKEN" ]; then
|
|
105
|
+
echo "ERROR: API token secret not found. Create repository secret named TEST_PYPI_API_TOKEN or PYPI_API_TOKEN."
|
|
106
|
+
exit 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# upload using twine to the selected repository URL
|
|
110
|
+
python -m twine upload --repository-url "$REPO_URL" -u __token__ -p "$TOKEN" dist/*
|
|
111
|
+
|
|
112
|
+
- name: Show success
|
|
113
|
+
run: echo "Published to ${{ steps.repoinfo.outputs.repository }} (if no errors above)."
|
jhcontext-0.2.0/LICENSE
ADDED
jhcontext-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jhcontext
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: PAC-AI: Protocol for Auditable Context in AI — Python SDK
|
|
5
|
+
Project-URL: Repository, https://github.com/jhdarosa/jhcontext
|
|
6
|
+
Project-URL: Documentation, https://github.com/jhdarosa/jhcontext#readme
|
|
7
|
+
Project-URL: Protocol Spec, https://github.com/jhdarosa/jhcontext-protocol
|
|
8
|
+
Author-email: jh <jh@jhcontext.com>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-act,auditability,context-management,multi-agent,provenance,w3c-prov
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: httpx>=0.27
|
|
22
|
+
Requires-Dist: pydantic>=2.0
|
|
23
|
+
Requires-Dist: rdflib>=7.0
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: aiosqlite>=0.20; extra == 'all'
|
|
26
|
+
Requires-Dist: crewai-tools>=1.9; extra == 'all'
|
|
27
|
+
Requires-Dist: crewai>=1.9; extra == 'all'
|
|
28
|
+
Requires-Dist: cryptography>=44.0; extra == 'all'
|
|
29
|
+
Requires-Dist: fastapi>=0.115; extra == 'all'
|
|
30
|
+
Requires-Dist: mcp>=1.0; extra == 'all'
|
|
31
|
+
Requires-Dist: uvicorn>=0.34; extra == 'all'
|
|
32
|
+
Provides-Extra: crewai
|
|
33
|
+
Requires-Dist: crewai-tools>=1.9; extra == 'crewai'
|
|
34
|
+
Requires-Dist: crewai>=1.9; extra == 'crewai'
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
39
|
+
Provides-Extra: server
|
|
40
|
+
Requires-Dist: aiosqlite>=0.20; extra == 'server'
|
|
41
|
+
Requires-Dist: cryptography>=44.0; extra == 'server'
|
|
42
|
+
Requires-Dist: fastapi>=0.115; extra == 'server'
|
|
43
|
+
Requires-Dist: mcp>=1.0; extra == 'server'
|
|
44
|
+
Requires-Dist: uvicorn>=0.34; extra == 'server'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# jhcontext SDK
|
|
48
|
+
|
|
49
|
+
**PAC-AI: Protocol for Auditable Context in AI** — Python SDK v0.2.0
|
|
50
|
+
|
|
51
|
+
A Python toolkit for building, signing, auditing, and serving AI context envelopes compliant with the PAC-AI protocol. Designed for EU AI Act compliance scenarios including temporal oversight (Art. 14) and negative proof (Art. 13).
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Core: models, builder, PROV, audit, crypto
|
|
57
|
+
pip install jhcontext
|
|
58
|
+
|
|
59
|
+
# With server (FastAPI + MCP + SQLite)
|
|
60
|
+
pip install "jhcontext[server]"
|
|
61
|
+
|
|
62
|
+
# With CrewAI integration
|
|
63
|
+
pip install "jhcontext[crewai]"
|
|
64
|
+
|
|
65
|
+
# Everything
|
|
66
|
+
pip install "jhcontext[all]"
|
|
67
|
+
|
|
68
|
+
# Development (adds pytest)
|
|
69
|
+
pip install "jhcontext[all,dev]"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Architecture
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
jhcontext/
|
|
76
|
+
├── models.py # Pydantic v2 data models (Envelope, Artifact, Decision, ...)
|
|
77
|
+
├── builder.py # EnvelopeBuilder — fluent API for constructing envelopes
|
|
78
|
+
├── prov.py # PROVGraph — W3C PROV graph builder (rdflib)
|
|
79
|
+
├── audit.py # Compliance verification (temporal oversight, negative proof, isolation)
|
|
80
|
+
├── crypto.py # SHA-256 hashing, Ed25519 signing (HMAC fallback)
|
|
81
|
+
├── canonicalize.py # Deterministic JSON serialization
|
|
82
|
+
├── semantics.py # UserML semantic payload helpers
|
|
83
|
+
├── cli.py # CLI: jhcontext serve | mcp | version
|
|
84
|
+
├── client/
|
|
85
|
+
│ └── api_client.py # REST client (httpx)
|
|
86
|
+
└── server/
|
|
87
|
+
├── app.py # FastAPI app factory
|
|
88
|
+
├── mcp_server.py # MCP server (stdio transport)
|
|
89
|
+
├── routes/ # REST API routes (envelopes, artifacts, decisions, provenance, compliance)
|
|
90
|
+
└── storage/
|
|
91
|
+
└── sqlite.py # SQLite backend (zero-config, ~/.jhcontext/)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Quick Start
|
|
95
|
+
|
|
96
|
+
### Build and sign an envelope
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from jhcontext import EnvelopeBuilder, RiskLevel, ArtifactType, observation, userml_payload
|
|
100
|
+
|
|
101
|
+
# Build semantic payload
|
|
102
|
+
payload = userml_payload(
|
|
103
|
+
observations=[observation("user:alice", "temperature", 22.3)],
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Build envelope
|
|
107
|
+
env = (
|
|
108
|
+
EnvelopeBuilder()
|
|
109
|
+
.set_producer("did:example:agent-1")
|
|
110
|
+
.set_scope("healthcare")
|
|
111
|
+
.set_risk_level(RiskLevel.HIGH)
|
|
112
|
+
.set_human_oversight(True)
|
|
113
|
+
.set_semantic_payload([payload])
|
|
114
|
+
.add_artifact(
|
|
115
|
+
artifact_id="art-vitals",
|
|
116
|
+
artifact_type=ArtifactType.TOKEN_SEQUENCE,
|
|
117
|
+
content_hash="sha256:abc123...",
|
|
118
|
+
)
|
|
119
|
+
.sign("did:example:agent-1")
|
|
120
|
+
.build()
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
print(env.context_id)
|
|
124
|
+
print(env.proof.content_hash)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Build a W3C PROV graph
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from jhcontext import PROVGraph
|
|
131
|
+
|
|
132
|
+
prov = (
|
|
133
|
+
PROVGraph("ctx-health-001")
|
|
134
|
+
.add_entity("vitals", "Patient Vitals", artifact_type="token_sequence")
|
|
135
|
+
.add_entity("recommendation", "AI Recommendation")
|
|
136
|
+
.add_activity("ai-analysis", "AI Analysis",
|
|
137
|
+
started_at="2026-01-01T10:00:00Z",
|
|
138
|
+
ended_at="2026-01-01T10:01:00Z")
|
|
139
|
+
.add_agent("agent-sensor", "Sensor Agent", role="data_collector")
|
|
140
|
+
.used("ai-analysis", "vitals")
|
|
141
|
+
.was_generated_by("recommendation", "ai-analysis")
|
|
142
|
+
.was_associated_with("ai-analysis", "agent-sensor")
|
|
143
|
+
.was_derived_from("recommendation", "vitals")
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Serialize
|
|
147
|
+
print(prov.serialize("turtle"))
|
|
148
|
+
|
|
149
|
+
# Query
|
|
150
|
+
chain = prov.get_causal_chain("recommendation")
|
|
151
|
+
used = prov.get_used_entities("ai-analysis")
|
|
152
|
+
sequence = prov.get_temporal_sequence()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Run compliance audits
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from jhcontext import (
|
|
159
|
+
verify_temporal_oversight,
|
|
160
|
+
verify_negative_proof,
|
|
161
|
+
verify_workflow_isolation,
|
|
162
|
+
verify_integrity,
|
|
163
|
+
generate_audit_report,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Art. 14 — Temporal oversight (human reviewed AFTER AI, >= 5 min)
|
|
167
|
+
result = verify_temporal_oversight(
|
|
168
|
+
prov,
|
|
169
|
+
ai_activity_id="ai-analysis",
|
|
170
|
+
human_activities=["doctor-review"],
|
|
171
|
+
min_review_seconds=300.0,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Art. 13 — Negative proof (excluded data types not in decision chain)
|
|
175
|
+
result = verify_negative_proof(
|
|
176
|
+
prov,
|
|
177
|
+
decision_entity_id="final-grade",
|
|
178
|
+
excluded_artifact_types=["biometric", "social_media"],
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Workflow isolation (two PROV graphs share zero artifacts)
|
|
182
|
+
result = verify_workflow_isolation(prov_a, prov_b)
|
|
183
|
+
|
|
184
|
+
# Envelope integrity (hash + signature)
|
|
185
|
+
result = verify_integrity(env)
|
|
186
|
+
|
|
187
|
+
# Generate full audit report
|
|
188
|
+
report = generate_audit_report(env, prov, [result1, result2, result3])
|
|
189
|
+
print(report.to_dict())
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Start the server
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# REST API on localhost:8400
|
|
196
|
+
jhcontext serve
|
|
197
|
+
|
|
198
|
+
# MCP server (stdio transport)
|
|
199
|
+
jhcontext mcp
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Use the REST client
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from jhcontext.client.api_client import JHContextClient
|
|
206
|
+
|
|
207
|
+
client = JHContextClient(base_url="http://localhost:8400")
|
|
208
|
+
|
|
209
|
+
# Submit envelope
|
|
210
|
+
ctx_id = client.submit_envelope(env)
|
|
211
|
+
|
|
212
|
+
# Retrieve
|
|
213
|
+
data = client.get_envelope(ctx_id)
|
|
214
|
+
|
|
215
|
+
# List with filters
|
|
216
|
+
envelopes = client.list_envelopes(scope="healthcare")
|
|
217
|
+
|
|
218
|
+
# Health check
|
|
219
|
+
print(client.health())
|
|
220
|
+
|
|
221
|
+
client.close()
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Testing
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
pip install -e ".[all,dev]"
|
|
228
|
+
pytest tests/ --ignore=tests/test_example.py -v
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Key Concepts
|
|
232
|
+
|
|
233
|
+
| Concept | Description |
|
|
234
|
+
|---------|-------------|
|
|
235
|
+
| **Envelope** | Immutable context unit: semantic payload + artifacts + provenance + proof |
|
|
236
|
+
| **Artifact** | Registered data object (embedding, token sequence, tool result) with content hash |
|
|
237
|
+
| **PROVGraph** | W3C PROV provenance graph (entities, activities, agents, relations) |
|
|
238
|
+
| **Proof** | Cryptographic integrity: canonical hash + Ed25519/HMAC signature |
|
|
239
|
+
| **Audit** | Compliance checks: temporal oversight, negative proof, workflow isolation |
|
|
240
|
+
| **UserML** | Semantic payload format: observation → interpretation → situation layers |
|
|
241
|
+
|
|
242
|
+
## Protocol
|
|
243
|
+
|
|
244
|
+
Based on the **PAC-AI** (Protocol for Auditable Context in AI) specification. JSON-LD schema at `jhcontext-protocol/jhcontext-core.jsonld` (v0.3).
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
Apache-2.0
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# jhcontext SDK
|
|
2
|
+
|
|
3
|
+
**PAC-AI: Protocol for Auditable Context in AI** — Python SDK v0.2.0
|
|
4
|
+
|
|
5
|
+
A Python toolkit for building, signing, auditing, and serving AI context envelopes compliant with the PAC-AI protocol. Designed for EU AI Act compliance scenarios including temporal oversight (Art. 14) and negative proof (Art. 13).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Core: models, builder, PROV, audit, crypto
|
|
11
|
+
pip install jhcontext
|
|
12
|
+
|
|
13
|
+
# With server (FastAPI + MCP + SQLite)
|
|
14
|
+
pip install "jhcontext[server]"
|
|
15
|
+
|
|
16
|
+
# With CrewAI integration
|
|
17
|
+
pip install "jhcontext[crewai]"
|
|
18
|
+
|
|
19
|
+
# Everything
|
|
20
|
+
pip install "jhcontext[all]"
|
|
21
|
+
|
|
22
|
+
# Development (adds pytest)
|
|
23
|
+
pip install "jhcontext[all,dev]"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
jhcontext/
|
|
30
|
+
├── models.py # Pydantic v2 data models (Envelope, Artifact, Decision, ...)
|
|
31
|
+
├── builder.py # EnvelopeBuilder — fluent API for constructing envelopes
|
|
32
|
+
├── prov.py # PROVGraph — W3C PROV graph builder (rdflib)
|
|
33
|
+
├── audit.py # Compliance verification (temporal oversight, negative proof, isolation)
|
|
34
|
+
├── crypto.py # SHA-256 hashing, Ed25519 signing (HMAC fallback)
|
|
35
|
+
├── canonicalize.py # Deterministic JSON serialization
|
|
36
|
+
├── semantics.py # UserML semantic payload helpers
|
|
37
|
+
├── cli.py # CLI: jhcontext serve | mcp | version
|
|
38
|
+
├── client/
|
|
39
|
+
│ └── api_client.py # REST client (httpx)
|
|
40
|
+
└── server/
|
|
41
|
+
├── app.py # FastAPI app factory
|
|
42
|
+
├── mcp_server.py # MCP server (stdio transport)
|
|
43
|
+
├── routes/ # REST API routes (envelopes, artifacts, decisions, provenance, compliance)
|
|
44
|
+
└── storage/
|
|
45
|
+
└── sqlite.py # SQLite backend (zero-config, ~/.jhcontext/)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
### Build and sign an envelope
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from jhcontext import EnvelopeBuilder, RiskLevel, ArtifactType, observation, userml_payload
|
|
54
|
+
|
|
55
|
+
# Build semantic payload
|
|
56
|
+
payload = userml_payload(
|
|
57
|
+
observations=[observation("user:alice", "temperature", 22.3)],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Build envelope
|
|
61
|
+
env = (
|
|
62
|
+
EnvelopeBuilder()
|
|
63
|
+
.set_producer("did:example:agent-1")
|
|
64
|
+
.set_scope("healthcare")
|
|
65
|
+
.set_risk_level(RiskLevel.HIGH)
|
|
66
|
+
.set_human_oversight(True)
|
|
67
|
+
.set_semantic_payload([payload])
|
|
68
|
+
.add_artifact(
|
|
69
|
+
artifact_id="art-vitals",
|
|
70
|
+
artifact_type=ArtifactType.TOKEN_SEQUENCE,
|
|
71
|
+
content_hash="sha256:abc123...",
|
|
72
|
+
)
|
|
73
|
+
.sign("did:example:agent-1")
|
|
74
|
+
.build()
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
print(env.context_id)
|
|
78
|
+
print(env.proof.content_hash)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Build a W3C PROV graph
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from jhcontext import PROVGraph
|
|
85
|
+
|
|
86
|
+
prov = (
|
|
87
|
+
PROVGraph("ctx-health-001")
|
|
88
|
+
.add_entity("vitals", "Patient Vitals", artifact_type="token_sequence")
|
|
89
|
+
.add_entity("recommendation", "AI Recommendation")
|
|
90
|
+
.add_activity("ai-analysis", "AI Analysis",
|
|
91
|
+
started_at="2026-01-01T10:00:00Z",
|
|
92
|
+
ended_at="2026-01-01T10:01:00Z")
|
|
93
|
+
.add_agent("agent-sensor", "Sensor Agent", role="data_collector")
|
|
94
|
+
.used("ai-analysis", "vitals")
|
|
95
|
+
.was_generated_by("recommendation", "ai-analysis")
|
|
96
|
+
.was_associated_with("ai-analysis", "agent-sensor")
|
|
97
|
+
.was_derived_from("recommendation", "vitals")
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Serialize
|
|
101
|
+
print(prov.serialize("turtle"))
|
|
102
|
+
|
|
103
|
+
# Query
|
|
104
|
+
chain = prov.get_causal_chain("recommendation")
|
|
105
|
+
used = prov.get_used_entities("ai-analysis")
|
|
106
|
+
sequence = prov.get_temporal_sequence()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Run compliance audits
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from jhcontext import (
|
|
113
|
+
verify_temporal_oversight,
|
|
114
|
+
verify_negative_proof,
|
|
115
|
+
verify_workflow_isolation,
|
|
116
|
+
verify_integrity,
|
|
117
|
+
generate_audit_report,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Art. 14 — Temporal oversight (human reviewed AFTER AI, >= 5 min)
|
|
121
|
+
result = verify_temporal_oversight(
|
|
122
|
+
prov,
|
|
123
|
+
ai_activity_id="ai-analysis",
|
|
124
|
+
human_activities=["doctor-review"],
|
|
125
|
+
min_review_seconds=300.0,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
# Art. 13 — Negative proof (excluded data types not in decision chain)
|
|
129
|
+
result = verify_negative_proof(
|
|
130
|
+
prov,
|
|
131
|
+
decision_entity_id="final-grade",
|
|
132
|
+
excluded_artifact_types=["biometric", "social_media"],
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Workflow isolation (two PROV graphs share zero artifacts)
|
|
136
|
+
result = verify_workflow_isolation(prov_a, prov_b)
|
|
137
|
+
|
|
138
|
+
# Envelope integrity (hash + signature)
|
|
139
|
+
result = verify_integrity(env)
|
|
140
|
+
|
|
141
|
+
# Generate full audit report
|
|
142
|
+
report = generate_audit_report(env, prov, [result1, result2, result3])
|
|
143
|
+
print(report.to_dict())
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Start the server
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# REST API on localhost:8400
|
|
150
|
+
jhcontext serve
|
|
151
|
+
|
|
152
|
+
# MCP server (stdio transport)
|
|
153
|
+
jhcontext mcp
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Use the REST client
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from jhcontext.client.api_client import JHContextClient
|
|
160
|
+
|
|
161
|
+
client = JHContextClient(base_url="http://localhost:8400")
|
|
162
|
+
|
|
163
|
+
# Submit envelope
|
|
164
|
+
ctx_id = client.submit_envelope(env)
|
|
165
|
+
|
|
166
|
+
# Retrieve
|
|
167
|
+
data = client.get_envelope(ctx_id)
|
|
168
|
+
|
|
169
|
+
# List with filters
|
|
170
|
+
envelopes = client.list_envelopes(scope="healthcare")
|
|
171
|
+
|
|
172
|
+
# Health check
|
|
173
|
+
print(client.health())
|
|
174
|
+
|
|
175
|
+
client.close()
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Testing
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
pip install -e ".[all,dev]"
|
|
182
|
+
pytest tests/ --ignore=tests/test_example.py -v
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Key Concepts
|
|
186
|
+
|
|
187
|
+
| Concept | Description |
|
|
188
|
+
|---------|-------------|
|
|
189
|
+
| **Envelope** | Immutable context unit: semantic payload + artifacts + provenance + proof |
|
|
190
|
+
| **Artifact** | Registered data object (embedding, token sequence, tool result) with content hash |
|
|
191
|
+
| **PROVGraph** | W3C PROV provenance graph (entities, activities, agents, relations) |
|
|
192
|
+
| **Proof** | Cryptographic integrity: canonical hash + Ed25519/HMAC signature |
|
|
193
|
+
| **Audit** | Compliance checks: temporal oversight, negative proof, workflow isolation |
|
|
194
|
+
| **UserML** | Semantic payload format: observation → interpretation → situation layers |
|
|
195
|
+
|
|
196
|
+
## Protocol
|
|
197
|
+
|
|
198
|
+
Based on the **PAC-AI** (Protocol for Auditable Context in AI) specification. JSON-LD schema at `jhcontext-protocol/jhcontext-core.jsonld` (v0.3).
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
Apache-2.0
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# jhcontext-sdk — Session Continuation Instructions
|
|
2
|
+
|
|
3
|
+
## What was done
|
|
4
|
+
|
|
5
|
+
### Paper (jhcontext-paper8pgs/)
|
|
6
|
+
- 8-page version of PAC-AI paper for IADIS AIS 2026 (Valencia, deadline Apr 10)
|
|
7
|
+
- Renamed PAC-P → **PAC-AI** (Protocol for Auditable Context in AI)
|
|
8
|
+
- Scenarios: Healthcare (Art. 14, temporal oversight) + Education (Art. 13, negative proof)
|
|
9
|
+
- IADIS formatting, APA bibliography, blind review ready
|
|
10
|
+
- Currently 9 pages (needs ~2 lines trimmed to fit 8)
|
|
11
|
+
- Figure 1 (pacp-layers.jpeg) still says "PAC-P" — needs regenerated image
|
|
12
|
+
|
|
13
|
+
### SDK (jhcontext-sdk/) — v0.2.0, IMPLEMENTED
|
|
14
|
+
Core modules all working and tested:
|
|
15
|
+
- `jhcontext/models.py` — Pydantic models (Envelope, Artifact, DecisionInfluence, Privacy, Compliance, Proof, Decision)
|
|
16
|
+
- `jhcontext/builder.py` — EnvelopeBuilder fluent API
|
|
17
|
+
- `jhcontext/prov.py` — PROVGraph (rdflib W3C PROV builder with query helpers)
|
|
18
|
+
- `jhcontext/audit.py` — verify_temporal_oversight, verify_negative_proof, verify_workflow_isolation, verify_integrity
|
|
19
|
+
- `jhcontext/crypto.py` — SHA-256, Ed25519 sign/verify (HMAC fallback without cryptography pkg)
|
|
20
|
+
- `jhcontext/canonicalize.py` — JSON deterministic serialization
|
|
21
|
+
- `jhcontext/semantics.py` — UserML helpers (observation, interpretation, situation)
|
|
22
|
+
- `jhcontext/server/app.py` — FastAPI app factory
|
|
23
|
+
- `jhcontext/server/routes/` — envelopes, artifacts, decisions, provenance, compliance routes
|
|
24
|
+
- `jhcontext/server/storage/sqlite.py` — SQLite backend (zero-config, ~/.jhcontext/)
|
|
25
|
+
- `jhcontext/server/mcp_server.py` — MCP server with tools (submit_envelope, get_envelope, query_prov, run_audit)
|
|
26
|
+
- `jhcontext/client/api_client.py` — REST client (httpx)
|
|
27
|
+
- `jhcontext/cli.py` — CLI: `jhcontext serve`, `jhcontext mcp`, `jhcontext version`
|
|
28
|
+
- `pyproject.toml` — hatchling, extras: [server], [crewai], [all], [dev]
|
|
29
|
+
|
|
30
|
+
### Protocol spec (jhcontext-protocol/)
|
|
31
|
+
- `jhcontext-core.jsonld` — Updated to v0.3 with artifacts_registry, decision_influence, privacy, compliance, scope, passed_artifact_pointer
|
|
32
|
+
|
|
33
|
+
### Agent definitions (jhcontext-agent/)
|
|
34
|
+
- `paper-agent.yaml` — Paper revision agent + task
|
|
35
|
+
- `author_actions.md` — Detailed plan with CrewAI agents for both scenarios
|
|
36
|
+
|
|
37
|
+
## What remains to be done
|
|
38
|
+
|
|
39
|
+
### Priority 1: Tests + README
|
|
40
|
+
- Write formal pytest tests for all modules (test_models, test_builder, test_prov, test_audit, test_crypto, test_storage, test_api)
|
|
41
|
+
- Write README.md with architecture overview, install modes, usage examples
|
|
42
|
+
- Run full test suite: `pip install -e ".[all,dev]" && pytest`
|
|
43
|
+
|
|
44
|
+
### Priority 2: jhcontext-usecases repo
|
|
45
|
+
- Create `/home/jhdarosa/Repos/jhcontext-usecases/`
|
|
46
|
+
- Healthcare scenario: 5 CrewAI agents (sensor→situation→decision→oversight→audit) using jhcontext SDK
|
|
47
|
+
- Education scenario: 4 CrewAI agents (ingestion→grading→equity→audit) with workflow isolation
|
|
48
|
+
- Agent YAML definitions are in `jhcontext-agent/author_actions.md` — use as reference
|
|
49
|
+
- Each scenario should produce: envelope JSON, PROV Turtle, audit report JSON
|
|
50
|
+
- Entry points: `python -m usecases.healthcare.run`, `python -m usecases.education.run`
|
|
51
|
+
|
|
52
|
+
### Priority 3: Server testing
|
|
53
|
+
- Test FastAPI server: `jhcontext serve` → hit endpoints with httpx
|
|
54
|
+
- Test MCP server: `jhcontext mcp` → verify tools work via stdio
|
|
55
|
+
- Test client↔server flow end-to-end
|
|
56
|
+
|
|
57
|
+
### Priority 4: Paper updates
|
|
58
|
+
- Trim paper to 8 pages (currently 9 — needs ~2 lines cut)
|
|
59
|
+
- Update Figure 1 image (still says PAC-P instead of PAC-AI)
|
|
60
|
+
- After usecases run: add implementation evidence to paper (envelope snippets, PROV graphs, metrics)
|
|
61
|
+
|
|
62
|
+
### Priority 5: Publish
|
|
63
|
+
- Publish jhcontext to PyPI: `python -m build && twine upload dist/*`
|
|
64
|
+
- Push to GitHub (public repo)
|
|
65
|
+
- For blind review: use anonymous.4open.science for paper reference
|
|
66
|
+
|
|
67
|
+
## Key files to read for context
|
|
68
|
+
1. `/home/jhdarosa/.claude/plans/cached-toasting-turing.md` — Full implementation plan
|
|
69
|
+
2. `/home/jhdarosa/Repos/jhcontext-agent/author_actions.md` — CrewAI agent definitions + scenario specs
|
|
70
|
+
3. `/home/jhdarosa/Repos/jhcontext-paper8pgs/sections/05scenarios.tex` — Paper scenario descriptions
|
|
71
|
+
4. `/home/jhdarosa/Repos/jhcontext-sdk/pyproject.toml` — Package structure and dependencies
|
|
72
|
+
|
|
73
|
+
## Quick verification commands
|
|
74
|
+
```bash
|
|
75
|
+
# Test SDK works
|
|
76
|
+
cd /home/jhdarosa/Repos/jhcontext-sdk
|
|
77
|
+
pip install -e ".[dev]"
|
|
78
|
+
python -c "from jhcontext import EnvelopeBuilder, PROVGraph; print('OK')"
|
|
79
|
+
|
|
80
|
+
# Start server
|
|
81
|
+
pip install -e ".[server]"
|
|
82
|
+
jhcontext serve # FastAPI on localhost:8400
|
|
83
|
+
|
|
84
|
+
# Start MCP
|
|
85
|
+
jhcontext mcp # stdio transport
|
|
86
|
+
```
|
jhcontext-0.2.0/cli.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Simple CLI to load a JSON file and print canonical form and hash
|
|
2
|
+
import sys, json
|
|
3
|
+
from jhcontext import from_dict
|
|
4
|
+
|
|
5
|
+
def main():
|
|
6
|
+
if len(sys.argv) < 2:
|
|
7
|
+
print('Usage: python cli.py envelope.json')
|
|
8
|
+
sys.exit(1)
|
|
9
|
+
path = sys.argv[1]
|
|
10
|
+
with open(path,'r',encoding='utf-8') as f:
|
|
11
|
+
d = json.load(f)
|
|
12
|
+
env = from_dict(d)
|
|
13
|
+
try:
|
|
14
|
+
env.validate()
|
|
15
|
+
except Exception as e:
|
|
16
|
+
print('Validation error:', e)
|
|
17
|
+
sys.exit(2)
|
|
18
|
+
print('Canonical:', env.canonical())
|
|
19
|
+
print('Hash:', env.hash())
|
|
20
|
+
proof = env.sign(env.raw.get('producer','did:example:unknown'))
|
|
21
|
+
print('Mock proof:', proof)
|
|
22
|
+
|
|
23
|
+
if __name__ == '__main__':
|
|
24
|
+
main()
|