capability-reasoning-kernel 0.4.2__tar.gz → 0.5.0rc2__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.
Files changed (112) hide show
  1. capability_reasoning_kernel-0.5.0rc2/.github/dependabot.yml +13 -0
  2. capability_reasoning_kernel-0.5.0rc2/.github/workflows/ci.yml +151 -0
  3. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/.github/workflows/pages.yml +3 -3
  4. capability_reasoning_kernel-0.5.0rc2/.github/workflows/release.yml +107 -0
  5. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/.pre-commit-config.yaml +2 -2
  6. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/CHANGELOG.md +60 -0
  7. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/PKG-INFO +36 -23
  8. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/README.md +24 -18
  9. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/SECURITY.md +7 -1
  10. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/docs/ANALYSIS-2026-07.md +3 -0
  11. capability_reasoning_kernel-0.5.0rc2/docs/CONFORMANCE.md +30 -0
  12. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/docs/DEVELOPMENT.md +26 -8
  13. capability_reasoning_kernel-0.5.0rc2/docs/OPERATIONS.md +149 -0
  14. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/docs/index.html +6 -6
  15. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/justfile +10 -4
  16. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/pyproject.toml +10 -4
  17. capability_reasoning_kernel-0.5.0rc2/scripts/check_artifacts.py +46 -0
  18. capability_reasoning_kernel-0.5.0rc2/scripts/check_published.py +57 -0
  19. capability_reasoning_kernel-0.5.0rc2/scripts/check_version.py +15 -0
  20. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/__init__.py +28 -3
  21. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/kernel/effects.py +175 -0
  22. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/kernel/gate.py +139 -0
  23. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/kernel/interpreter.py +118 -64
  24. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/kernel/runtime.py +63 -0
  25. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/kernel/session.py +61 -0
  26. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/memory/sink.py +212 -0
  27. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/memory/trace.py +150 -0
  28. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/anthropic.py +14 -3
  29. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/base.py +53 -2
  30. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/deepseek.py +4 -0
  31. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/openai.py +69 -30
  32. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/parse.py +11 -3
  33. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/reasoner/telemetry.py +36 -0
  34. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/capability.py +1 -1
  35. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/schemas/limits.py +36 -0
  36. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/registry.py +4 -1
  37. capability_reasoning_kernel-0.5.0rc2/src/reasoning_kernel/schemas/trace.py +184 -0
  38. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/tools/demo_mail.py +6 -3
  39. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/tools/registry.py +6 -0
  40. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_interpreter_loop.py +4 -2
  41. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_no_bypass_conformance.py +7 -3
  42. capability_reasoning_kernel-0.5.0rc2/tests/test_operational.py +729 -0
  43. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_parse_with_schema.py +24 -1
  44. capability_reasoning_kernel-0.5.0rc2/tests/test_provider_contracts.py +170 -0
  45. capability_reasoning_kernel-0.5.0rc2/tests/test_providers_live.py +183 -0
  46. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_reasoner_robustness.py +3 -3
  47. capability_reasoning_kernel-0.5.0rc2/tests/test_release_contract.py +88 -0
  48. capability_reasoning_kernel-0.5.0rc2/uv.lock +1082 -0
  49. capability_reasoning_kernel-0.4.2/.github/workflows/ci.yml +0 -73
  50. capability_reasoning_kernel-0.4.2/.github/workflows/release.yml +0 -55
  51. capability_reasoning_kernel-0.4.2/src/reasoning_kernel/kernel/effects.py +0 -90
  52. capability_reasoning_kernel-0.4.2/src/reasoning_kernel/kernel/gate.py +0 -92
  53. capability_reasoning_kernel-0.4.2/src/reasoning_kernel/memory/trace.py +0 -23
  54. capability_reasoning_kernel-0.4.2/src/reasoning_kernel/schemas/limits.py +0 -23
  55. capability_reasoning_kernel-0.4.2/src/reasoning_kernel/schemas/trace.py +0 -110
  56. capability_reasoning_kernel-0.4.2/tests/test_providers_live.py +0 -54
  57. capability_reasoning_kernel-0.4.2/uv.lock +0 -603
  58. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/.env.example +0 -0
  59. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/.gitignore +0 -0
  60. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/.python-version +0 -0
  61. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/CLAUDE.md +0 -0
  62. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/LICENSE +0 -0
  63. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/docs/.nojekyll +0 -0
  64. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/docs/favicon.svg +0 -0
  65. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/config.py +0 -0
  66. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/context/__init__.py +0 -0
  67. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/context/assembler.py +0 -0
  68. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/__init__.py +0 -0
  69. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/_report.py +0 -0
  70. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/email_exfil.py +0 -0
  71. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/live_run.py +0 -0
  72. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/merge.py +0 -0
  73. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/reasoner_error.py +0 -0
  74. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/run_limits.py +0 -0
  75. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/demo/subkernel.py +0 -0
  76. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/kernel/__init__.py +0 -0
  77. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/kernel/taint.py +0 -0
  78. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/memory/__init__.py +0 -0
  79. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/memory/store.py +0 -0
  80. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/py.typed +0 -0
  81. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/__init__.py +0 -0
  82. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/factory.py +0 -0
  83. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/fake.py +0 -0
  84. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/reasoner/roles.py +0 -0
  85. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/__init__.py +0 -0
  86. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/ids.py +0 -0
  87. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/plan.py +0 -0
  88. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/policy.py +0 -0
  89. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/provenance.py +0 -0
  90. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/schemas/values.py +0 -0
  91. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/src/reasoning_kernel/tools/__init__.py +0 -0
  92. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/conftest.py +0 -0
  93. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_capability.py +0 -0
  94. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_composition.py +0 -0
  95. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_declass_policy.py +0 -0
  96. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_demo_email_exfil.py +0 -0
  97. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_demo_mail_tools.py +0 -0
  98. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_gate_capability.py +0 -0
  99. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_gate_provenance_declassify.py +0 -0
  100. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_gate_unrestricted_readers.py +0 -0
  101. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_invariant_a.py +0 -0
  102. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_merge.py +0 -0
  103. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_plan_schema.py +0 -0
  104. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_provenance_propagation.py +0 -0
  105. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_public_api.py +0 -0
  106. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_reasoner_factory.py +0 -0
  107. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_registry.py +0 -0
  108. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_run_limits.py +0 -0
  109. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_store.py +0 -0
  110. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_subject_provenance.py +0 -0
  111. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_subkernel.py +0 -0
  112. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0rc2}/tests/test_trace_append_only.py +0 -0
@@ -0,0 +1,13 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ github-actions:
9
+ patterns: ["*"]
10
+ - package-ecosystem: uv
11
+ directory: /
12
+ schedule:
13
+ interval: weekly
@@ -0,0 +1,151 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+ inputs:
9
+ live_providers:
10
+ description: Comma-separated providers required by the live gate
11
+ required: true
12
+ default: deepseek
13
+ type: string
14
+ workflow_call:
15
+ inputs:
16
+ live_providers:
17
+ description: Comma-separated providers required by the live gate
18
+ required: false
19
+ default: ""
20
+ type: string
21
+ secrets:
22
+ ANTHROPIC_API_KEY:
23
+ required: false
24
+ OPENAI_API_KEY:
25
+ required: false
26
+ DEEPSEEK_API_KEY:
27
+ required: false
28
+
29
+ permissions:
30
+ contents: read
31
+
32
+ concurrency:
33
+ group: ci-${{ github.ref }}
34
+ cancel-in-progress: true
35
+
36
+ jobs:
37
+ quality:
38
+ runs-on: ubuntu-latest
39
+ strategy:
40
+ fail-fast: false
41
+ matrix:
42
+ python-version: ["3.12", "3.13", "3.14"]
43
+ steps:
44
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
45
+ with:
46
+ persist-credentials: false
47
+
48
+ - name: Install uv
49
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
50
+ with:
51
+ version: "0.12.10"
52
+ checksum: "173d95a0c32d18c896c46ba6fafbf3cf9c14ab74b033f81b76c883ef492a976b"
53
+ python-version: ${{ matrix.python-version }}
54
+ enable-cache: true
55
+
56
+ - name: Install just
57
+ uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
58
+
59
+ - name: Sync dependencies
60
+ run: uv sync --all-extras --locked
61
+
62
+ # The justfile uses `set dotenv-load`; provide a no-secret env so it loads cleanly.
63
+ # The default suite is key-free and `live` tests are excluded via addopts -m 'not live'.
64
+ - name: Prepare env
65
+ run: cp .env.example .env
66
+
67
+ - name: Lint
68
+ run: just lint
69
+
70
+ - name: Typecheck
71
+ run: just typecheck
72
+
73
+ - name: Test
74
+ run: just test # runs with coverage; fails under the threshold in pyproject
75
+
76
+ - name: Verify distribution
77
+ run: just package-check
78
+
79
+ artifact-roundtrip:
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
83
+ with:
84
+ persist-credentials: false
85
+
86
+ - name: Install uv
87
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
88
+ with:
89
+ version: "0.12.10"
90
+ checksum: "173d95a0c32d18c896c46ba6fafbf3cf9c14ab74b033f81b76c883ef492a976b"
91
+ python-version: "3.12"
92
+ enable-cache: true
93
+
94
+ - name: Build distribution
95
+ run: |
96
+ uv sync --all-extras --locked
97
+ uv build --clear
98
+ uv run twine check --strict dist/*
99
+ uv run python scripts/check_artifacts.py dist
100
+ sha256sum dist/* > SHA256SUMS
101
+
102
+ - name: Upload distribution
103
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
104
+ with:
105
+ name: ci-distribution
106
+ path: |
107
+ dist/
108
+ SHA256SUMS
109
+ if-no-files-found: error
110
+ retention-days: 1
111
+
112
+ - name: Download distribution
113
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
114
+ with:
115
+ name: ci-distribution
116
+ path: roundtrip
117
+
118
+ - name: Verify downloaded bytes
119
+ working-directory: roundtrip
120
+ run: sha256sum --check SHA256SUMS
121
+
122
+ # Explicit provider qualification: manual or required by the release's reusable workflow call.
123
+ live:
124
+ if: inputs.live_providers != ''
125
+ runs-on: ubuntu-latest
126
+ steps:
127
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
128
+ with:
129
+ persist-credentials: false
130
+
131
+ - name: Install uv
132
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
133
+ with:
134
+ version: "0.12.10"
135
+ checksum: "173d95a0c32d18c896c46ba6fafbf3cf9c14ab74b033f81b76c883ef492a976b"
136
+ python-version: "3.12"
137
+ enable-cache: true
138
+
139
+ - name: Install just
140
+ uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
141
+
142
+ - name: Sync dependencies
143
+ run: uv sync --all-extras --locked
144
+
145
+ - name: Run live provider tests
146
+ env:
147
+ RK_LIVE_PROVIDERS: ${{ inputs.live_providers }}
148
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
149
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
150
+ DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
151
+ run: just test-live
@@ -29,12 +29,12 @@ jobs:
29
29
  url: ${{ steps.deployment.outputs.page_url }}
30
30
  steps:
31
31
  # Actions pinned to immutable commit SHAs (supply-chain hardening); tag in comment.
32
- - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
33
  with:
34
34
  persist-credentials: false
35
35
 
36
36
  - name: Configure Pages
37
- uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
37
+ uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
38
38
  with:
39
39
  enablement: true # self-enable Pages (build_type=workflow) on first run — no manual Settings step
40
40
 
@@ -45,4 +45,4 @@ jobs:
45
45
 
46
46
  - name: Deploy to GitHub Pages
47
47
  id: deployment
48
- uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
48
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
@@ -0,0 +1,107 @@
1
+ name: Release
2
+
3
+ # Test the tagged commit, then promote one immutable distribution through both indexes.
4
+ on:
5
+ push:
6
+ tags: ["v*"]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: release-${{ github.ref }}
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ quality:
17
+ uses: ./.github/workflows/ci.yml
18
+ with:
19
+ live_providers: deepseek
20
+ secrets:
21
+ DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
22
+
23
+ build:
24
+ needs: quality
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
28
+ with:
29
+ persist-credentials: false
30
+ - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
31
+ with:
32
+ version: "0.12.10"
33
+ checksum: "173d95a0c32d18c896c46ba6fafbf3cf9c14ab74b033f81b76c883ef492a976b"
34
+ python-version: "3.12"
35
+ - run: uv sync --all-extras --locked
36
+ - name: Validate tag and build
37
+ run: |
38
+ uv run python scripts/check_version.py
39
+ uv build --clear
40
+ uv run twine check --strict dist/*
41
+ uv run python scripts/check_artifacts.py dist
42
+ sha256sum dist/* > SHA256SUMS
43
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
44
+ with:
45
+ name: distribution
46
+ path: |
47
+ dist/
48
+ SHA256SUMS
49
+ if-no-files-found: error
50
+
51
+ testpypi:
52
+ needs: build
53
+ runs-on: ubuntu-latest
54
+ environment: testpypi
55
+ permissions:
56
+ contents: read
57
+ id-token: write
58
+ steps:
59
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
60
+ with:
61
+ name: distribution
62
+ - run: sha256sum --check SHA256SUMS
63
+ - name: Publish to TestPyPI
64
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
65
+ with:
66
+ repository-url: https://test.pypi.org/legacy/
67
+
68
+ verify-testpypi:
69
+ needs: testpypi
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
73
+ with:
74
+ persist-credentials: false
75
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
76
+ with:
77
+ name: distribution
78
+ - run: sha256sum --check SHA256SUMS
79
+ - run: python scripts/check_published.py dist testpypi
80
+
81
+ pypi:
82
+ needs: verify-testpypi
83
+ runs-on: ubuntu-latest
84
+ environment: pypi
85
+ permissions:
86
+ contents: read
87
+ id-token: write
88
+ steps:
89
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
90
+ with:
91
+ name: distribution
92
+ - run: sha256sum --check SHA256SUMS
93
+ - name: Publish to PyPI
94
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
95
+
96
+ verify-pypi:
97
+ needs: pypi
98
+ runs-on: ubuntu-latest
99
+ steps:
100
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
101
+ with:
102
+ persist-credentials: false
103
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
104
+ with:
105
+ name: distribution
106
+ - run: sha256sum --check SHA256SUMS
107
+ - run: python scripts/check_published.py dist pypi
@@ -16,13 +16,13 @@ repos:
16
16
  - id: ruff-check
17
17
  name: ruff check --fix (uv.lock version, same as `just fix`)
18
18
  language: system
19
- entry: uv run ruff check --fix src/ tests/
19
+ entry: uv run ruff check --fix src/ tests/ scripts/
20
20
  pass_filenames: false
21
21
  types_or: [python, pyi]
22
22
  - id: ruff-format
23
23
  name: ruff format (uv.lock version, same as `just fix`)
24
24
  language: system
25
- entry: uv run ruff format src/ tests/
25
+ entry: uv run ruff format src/ tests/ scripts/
26
26
  pass_filenames: false
27
27
  types_or: [python, pyi]
28
28
  - id: pyright
@@ -4,6 +4,64 @@ All notable changes to this project are documented here. The format is based on
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.5.0rc2] - 2026-09-06
8
+
9
+ Maintenance candidate following the first published operational release. Publication remains
10
+ separate from live host-adapter acceptance.
11
+
12
+ ### Added
13
+
14
+ - SQLite audit discovery for reserved run IDs and runs needing operator review after incomplete or
15
+ uncertain execution.
16
+
17
+ ### Changed
18
+
19
+ - Validate the provider adapters against OpenAI SDK 3.7 and Anthropic SDK 1.4, while bounding their
20
+ optional dependency ranges below the next untested major versions.
21
+ - Upgrade SHA-pinned GitHub Actions and add a CI upload/download checksum round trip for release
22
+ artifacts; group future Actions updates into one Dependabot pull request.
23
+ - Refresh the locked Pydantic, pytest and ruff versions used by CI and local development.
24
+
25
+ ### Fixed
26
+
27
+ - Package builds clear stale distributions, while published-artifact verification ignores unrelated
28
+ files and still requires exactly one wheel and one source distribution.
29
+
30
+ ## [0.5.0rc1] - 2026-09-06
31
+
32
+ Published operational embedding candidate. Publication does not imply live-adapter UAT.
33
+
34
+ ### Added
35
+
36
+ - Single-use `RunSession`, bounded operational defaults and root-wide step/tool/parser/LLM budgets.
37
+ - Explicit tool egress declarations, normalized input verification and output model revalidation.
38
+ - `TraceSink`, memory/SQLite sinks, durable pre-call records and fail-closed storage handling.
39
+ - Correlated invocation IDs, parent run IDs, partial/uncertain effect outcomes and terminal run status.
40
+ - Redacted operational events, detached snapshots and canonical detailed digests.
41
+ - Bounded shared reasoner executor, returned usage/latency capture and public provider result types.
42
+ - Sanitized provider failure categories, HTTP status and allow-listed operational error codes.
43
+ - Crash, concurrency, shared-budget, adapter-contract and provider failure regression tests.
44
+ - Python 3.14 CI, locked dependencies, pinned actions and single-artifact release promotion with
45
+ a pinned/checksummed uv runtime, version checks, isolated wheel smoke and served-byte verification.
46
+ - Operational/migration guide and conformance checklist.
47
+
48
+ ### Changed
49
+
50
+ - Require a patched `pydantic-settings>=2.14.2` (GHSA-4xgf-cpjx-pc3j) and refresh its lock entry.
51
+ - Version the SQLite audit schema, migrate the unversioned candidate layout, reject unknown/newer
52
+ layouts or missing key constraints, and verify released bytes after TestPyPI and PyPI publication.
53
+ - Require an explicit live-provider set in release CI; `0.5.0rc1` qualifies DeepSeek while OpenAI
54
+ remains supported but is not live-qualified for this candidate.
55
+ - Low-level interpreters reject reuse and context/trace mismatches; child IDs are opaque.
56
+ - Limits span descendants; `RunLimits()` remains unbounded for explicit low-level wiring.
57
+ - Failed tools stop later steps without implying rollback; output validation cannot undo a call.
58
+ - OpenAI-compatible fallback uses structured error parameters, once; refusals/truncations and
59
+ malformed outputs are terminal errors. DeepSeek routes directly through JSON mode with local
60
+ schema validation because its compatible API does not implement OpenAI's native JSON Schema mode.
61
+ Provider exception messages no longer include raw API text.
62
+ - Pyright explicitly resolves the project virtualenv. Documentation distinguishes root planning,
63
+ delegated untrusted planning and partial effects.
64
+
7
65
  ## [0.4.2] - 2026-07-10
8
66
 
9
67
  A correctness release for the gate's provenance stage, plus fail-closed hardening of the provider
@@ -143,6 +201,8 @@ Initial reference implementation of the Reasoning Kernel pattern (strong / CaMeL
143
201
  invariants, no-effect-bypasses-the-Verifier by construction, the deterministic declassification seam,
144
202
  and the worked email-exfiltration demo.
145
203
 
204
+ [0.5.0rc2]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.5.0rc2
205
+ [0.5.0rc1]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.5.0rc1
146
206
  [0.4.2]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.4.2
147
207
  [0.4.1]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.4.1
148
208
  [0.4.0]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.4.0
@@ -1,10 +1,12 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: capability-reasoning-kernel
3
- Version: 0.4.2
3
+ Version: 0.5.0rc2
4
4
  Summary: Reference implementation of the Reasoning Kernel pattern (strong / CaMeL-like form)
5
5
  Project-URL: Homepage, https://github.com/gianlucamazza/reasoning-kernel
6
6
  Project-URL: Repository, https://github.com/gianlucamazza/reasoning-kernel
7
7
  Project-URL: Issues, https://github.com/gianlucamazza/reasoning-kernel/issues
8
+ Project-URL: Documentation, https://github.com/gianlucamazza/reasoning-kernel/blob/main/docs/OPERATIONS.md
9
+ Project-URL: Changelog, https://github.com/gianlucamazza/reasoning-kernel/blob/main/CHANGELOG.md
8
10
  Author: Gianluca Mazza — Venere Labs
9
11
  License: MIT
10
12
  License-File: LICENSE
@@ -15,19 +17,24 @@ Classifier: License :: OSI Approved :: MIT License
15
17
  Classifier: Programming Language :: Python :: 3
16
18
  Classifier: Programming Language :: Python :: 3.12
17
19
  Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
18
21
  Classifier: Topic :: Security
19
22
  Classifier: Typing :: Typed
20
23
  Requires-Python: >=3.12
21
- Requires-Dist: pydantic-settings>=2.0
24
+ Requires-Dist: pydantic-settings>=2.14.2
22
25
  Requires-Dist: pydantic>=2.7
23
26
  Provides-Extra: dev
27
+ Requires-Dist: anthropic<2,>=0.40; extra == 'dev'
28
+ Requires-Dist: httpx2<3,>=2.12; extra == 'dev'
29
+ Requires-Dist: openai<4,>=1.50; extra == 'dev'
24
30
  Requires-Dist: pyright>=1.1.380; extra == 'dev'
25
31
  Requires-Dist: pytest-cov>=5.0; extra == 'dev'
26
32
  Requires-Dist: pytest>=8.0; extra == 'dev'
27
33
  Requires-Dist: ruff>=0.9; extra == 'dev'
34
+ Requires-Dist: twine>=6.0; extra == 'dev'
28
35
  Provides-Extra: providers
29
- Requires-Dist: anthropic>=0.40; extra == 'providers'
30
- Requires-Dist: openai>=1.50; extra == 'providers'
36
+ Requires-Dist: anthropic<2,>=0.40; extra == 'providers'
37
+ Requires-Dist: openai<4,>=1.50; extra == 'providers'
31
38
  Description-Content-Type: text/markdown
32
39
 
33
40
  # Reasoning Kernel
@@ -67,8 +74,9 @@ It is a reference implementation, **not** a turn-key security product.
67
74
  The pattern guarantees a **topology, not a property**: it fixes *where* mediation and verification
68
75
  live, by construction; it does not guarantee any particular policy is safe. Conformance is a
69
76
  *necessary*, not a *sufficient*, condition. Concretely: no matter what an injected message says, it can
70
- never reach the planner nor fire a tool without passing your Gate — that boundary holds by
71
- construction; whether your Gate's *policy* is correct is on you.
77
+ cannot fire a tool without passing your Gate. The root planner is isolated from tool results;
78
+ delegated sub-planners deliberately see untrusted data under reduced grants. Whether your Gate's
79
+ *policy* is correct is on you.
72
80
 
73
81
  ## Strong form: no trusted reasoner
74
82
 
@@ -96,19 +104,19 @@ The trusted, deterministic kernel is the **interpreter + capability/provenance g
96
104
 
97
105
  Reasoner providers: Anthropic, OpenAI, Deepseek (OpenAI-compatible, reusing the `openai` SDK via a
98
106
  `base_url` — no separate dependency), plus a deterministic `FakeProvider` for key-free tests — all
99
- behind one interface (`reasoner/base.py`). The fungibility corollary is validated live: OpenAI and
100
- Deepseek return schema-valid `Plan`s through the same interface (`just test-live`); Anthropic is
101
- exercised on demand when its key is set.
107
+ behind one interface (`reasoner/base.py`). Configured providers can be exercised through the same
108
+ live contract (`just test-live`). The 0.5 release workflow requires DeepSeek qualification; OpenAI
109
+ and Anthropic remain independently contract-tested unless a release explicitly qualifies them live.
102
110
 
103
111
  ## No effect bypasses the Verifier — by construction
104
112
 
105
113
  1. Tool callables live only in `ToolRegistry`, handed only to `EffectDispatcher`; the interpreter
106
114
  never holds one.
107
- 2. `EffectDispatcher` cannot be constructed without a `Gate`, and `dispatch` checks it
115
+ 2. `EffectDispatcher` cannot be constructed without a `Gate`, and `dispatch` authorizes the call
108
116
  unconditionally before the callable runs.
109
117
  3. `ToolCallStep` is the only step kind that invokes a tool callable, and its only handler routes
110
118
  through the dispatcher. The other step kinds (`const`, `q_parse`, `subkernel`, `merge`) produce
111
- values, never external effects.
119
+ values; a sub-kernel may invoke tools through its reduced Gate and the same dispatcher path.
112
120
 
113
121
  ## What a run looks like
114
122
 
@@ -136,9 +144,9 @@ just demo-limits # termination: RunLimits aborts the run closed before th
136
144
  just demo-reasoner-error # fail-closed: a failing reasoner commits nothing (plan_rejected)
137
145
  just demo-merge # MergeStep: combine several reads into one value; taint flows through the join
138
146
 
139
- uv sync --all-extras # adds the provider SDKs for the live flows below
147
+ uv sync --all-extras # explicit provider extra (dev also includes SDKs for mock tests)
140
148
  just demo-live # end-to-end with a REAL planner/parser (needs a key in .env)
141
- just test-live # optional: real Anthropic/OpenAI/Deepseek round-trips (needs API keys)
149
+ just test-live # configured real-provider round-trips; RK_LIVE_PROVIDERS makes a set mandatory
142
150
  ```
143
151
 
144
152
  See [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) for the quality bar (coverage gate, strict typing,
@@ -149,9 +157,15 @@ pre-commit) and how to configure provider keys. Release notes are in
149
157
 
150
158
  Install: `pip install capability-reasoning-kernel` — it **imports as** `import reasoning_kernel`
151
159
  (the PyPI name differs because `reasoning-kernel` was taken by an unrelated project).
160
+ Install the operational candidate explicitly with
161
+ `pip install capability-reasoning-kernel==0.5.0rc2`.
152
162
 
153
- There is no facade: you wire the parts explicitly, which is the point — every trusted seam is visible.
154
- The package root re-exports the building blocks. Sketch (see
163
+ For operational embedding, use `RunSession` with a persistent sink and bounded defaults; see
164
+ [operations and migration](docs/OPERATIONS.md) and the [conformance checklist](docs/CONFORMANCE.md).
165
+ It isolates each run, records partial effects and refuses automatic replay. The 0.5 line is a
166
+ published pre-release; package publication is not evidence of validated host integration.
167
+
168
+ Explicit low-level wiring remains available. The package root re-exports the building blocks. Sketch (see
155
169
  [`demo/email_exfil.py`](src/reasoning_kernel/demo/email_exfil.py) for a complete, runnable version):
156
170
 
157
171
  ```python
@@ -205,9 +219,8 @@ result = kernel.run(ctx) # RunResult(trace, committed); committed is
205
219
  - **Reasoner failure is fail-closed**: a provider that returns no usable output (empty / refused /
206
220
  malformed) raises `ReasonerError` (`reasoner/base.py`), and a provider call that fails in transport
207
221
  (rate limit exhausted, 5xx, network fault) raises its `TransportError` subclass; either way the
208
- Conductor records a terminal trace event and commits nothing, rather than crashing or acting on a
209
- partial result. Treating the model as untrusted compute
210
- means a flaky reasoner can never produce a half-applied effect.
222
+ Conductor records a terminal trace event and stops subsequent work. Earlier effects remain real
223
+ and are reported in `RunResult.effects`; `committed=None` means no final value, not rollback.
211
224
  - **Capability composition (§5.4)**: every reasoner is bound to a `CapabilitySet`; the kernel rejects a
212
225
  reasoner whose grant exceeds the dispatcher's — a child can never widen authority. A `SubKernelStep`
213
226
  delegates untrusted content to an inner kernel at a **clamped, reduced grant**: an injection in that
@@ -216,9 +229,9 @@ result = kernel.run(ctx) # RunResult(trace, committed); committed is
216
229
  - **Static, data-independent control flow**: a `Plan` is a forward-only DAG of five step kinds
217
230
  (`const`, `tool`, `q_parse`, `subkernel`, `merge`), executed linearly by `kernel/interpreter.py`; a
218
231
  `QuarantineParseStep`'s target schema is fixed at plan time
219
- (`schema_ref`), never chosen on the quarantined value. No branch, loop, or tool selection is
220
- conditioned on untrusted content — so control-flow leaks of quarantined data are precluded by
221
- construction, not by policy (the matching cost is in *Honest limits*).
232
+ (`schema_ref`), never chosen on the quarantined value. There are no runtime branches or loops.
233
+ Delegated sub-planners can choose a child plan based on untrusted input; its authority and literal
234
+ provenance are reduced accordingly. This is not a claim of data-independent planning across delegation.
222
235
 
223
236
  ## Honest limits (fundamental — localized, not dissolved)
224
237
 
@@ -256,7 +269,7 @@ result = kernel.run(ctx) # RunResult(trace, committed); committed is
256
269
  - **Join** — combining values combines their labels conservatively (union of sources, intersection of
257
270
  readers, union of subjects), so taint only ever increases.
258
271
  - **Quarantine** — routing untrusted content through the Q-LLM, which cannot launder its taint.
259
- - **Capability / grant** — an unforgeable permission a tool requires; a run holds a fixed
272
+ - **Capability / grant** — a host-issued permission a tool requires; a run holds a fixed
260
273
  `CapabilitySet` (its *grant*), and a sub-kernel's grant can only ever shrink.
261
274
  - **Declassifier (`DeclassPolicy`)** — the single deterministic seam that may let tainted data into a
262
275
  WRITE; the one place trust is deliberately relaxed.
@@ -35,8 +35,9 @@ It is a reference implementation, **not** a turn-key security product.
35
35
  The pattern guarantees a **topology, not a property**: it fixes *where* mediation and verification
36
36
  live, by construction; it does not guarantee any particular policy is safe. Conformance is a
37
37
  *necessary*, not a *sufficient*, condition. Concretely: no matter what an injected message says, it can
38
- never reach the planner nor fire a tool without passing your Gate — that boundary holds by
39
- construction; whether your Gate's *policy* is correct is on you.
38
+ cannot fire a tool without passing your Gate. The root planner is isolated from tool results;
39
+ delegated sub-planners deliberately see untrusted data under reduced grants. Whether your Gate's
40
+ *policy* is correct is on you.
40
41
 
41
42
  ## Strong form: no trusted reasoner
42
43
 
@@ -64,19 +65,19 @@ The trusted, deterministic kernel is the **interpreter + capability/provenance g
64
65
 
65
66
  Reasoner providers: Anthropic, OpenAI, Deepseek (OpenAI-compatible, reusing the `openai` SDK via a
66
67
  `base_url` — no separate dependency), plus a deterministic `FakeProvider` for key-free tests — all
67
- behind one interface (`reasoner/base.py`). The fungibility corollary is validated live: OpenAI and
68
- Deepseek return schema-valid `Plan`s through the same interface (`just test-live`); Anthropic is
69
- exercised on demand when its key is set.
68
+ behind one interface (`reasoner/base.py`). Configured providers can be exercised through the same
69
+ live contract (`just test-live`). The 0.5 release workflow requires DeepSeek qualification; OpenAI
70
+ and Anthropic remain independently contract-tested unless a release explicitly qualifies them live.
70
71
 
71
72
  ## No effect bypasses the Verifier — by construction
72
73
 
73
74
  1. Tool callables live only in `ToolRegistry`, handed only to `EffectDispatcher`; the interpreter
74
75
  never holds one.
75
- 2. `EffectDispatcher` cannot be constructed without a `Gate`, and `dispatch` checks it
76
+ 2. `EffectDispatcher` cannot be constructed without a `Gate`, and `dispatch` authorizes the call
76
77
  unconditionally before the callable runs.
77
78
  3. `ToolCallStep` is the only step kind that invokes a tool callable, and its only handler routes
78
79
  through the dispatcher. The other step kinds (`const`, `q_parse`, `subkernel`, `merge`) produce
79
- values, never external effects.
80
+ values; a sub-kernel may invoke tools through its reduced Gate and the same dispatcher path.
80
81
 
81
82
  ## What a run looks like
82
83
 
@@ -104,9 +105,9 @@ just demo-limits # termination: RunLimits aborts the run closed before th
104
105
  just demo-reasoner-error # fail-closed: a failing reasoner commits nothing (plan_rejected)
105
106
  just demo-merge # MergeStep: combine several reads into one value; taint flows through the join
106
107
 
107
- uv sync --all-extras # adds the provider SDKs for the live flows below
108
+ uv sync --all-extras # explicit provider extra (dev also includes SDKs for mock tests)
108
109
  just demo-live # end-to-end with a REAL planner/parser (needs a key in .env)
109
- just test-live # optional: real Anthropic/OpenAI/Deepseek round-trips (needs API keys)
110
+ just test-live # configured real-provider round-trips; RK_LIVE_PROVIDERS makes a set mandatory
110
111
  ```
111
112
 
112
113
  See [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) for the quality bar (coverage gate, strict typing,
@@ -117,9 +118,15 @@ pre-commit) and how to configure provider keys. Release notes are in
117
118
 
118
119
  Install: `pip install capability-reasoning-kernel` — it **imports as** `import reasoning_kernel`
119
120
  (the PyPI name differs because `reasoning-kernel` was taken by an unrelated project).
121
+ Install the operational candidate explicitly with
122
+ `pip install capability-reasoning-kernel==0.5.0rc2`.
120
123
 
121
- There is no facade: you wire the parts explicitly, which is the point — every trusted seam is visible.
122
- The package root re-exports the building blocks. Sketch (see
124
+ For operational embedding, use `RunSession` with a persistent sink and bounded defaults; see
125
+ [operations and migration](docs/OPERATIONS.md) and the [conformance checklist](docs/CONFORMANCE.md).
126
+ It isolates each run, records partial effects and refuses automatic replay. The 0.5 line is a
127
+ published pre-release; package publication is not evidence of validated host integration.
128
+
129
+ Explicit low-level wiring remains available. The package root re-exports the building blocks. Sketch (see
123
130
  [`demo/email_exfil.py`](src/reasoning_kernel/demo/email_exfil.py) for a complete, runnable version):
124
131
 
125
132
  ```python
@@ -173,9 +180,8 @@ result = kernel.run(ctx) # RunResult(trace, committed); committed is
173
180
  - **Reasoner failure is fail-closed**: a provider that returns no usable output (empty / refused /
174
181
  malformed) raises `ReasonerError` (`reasoner/base.py`), and a provider call that fails in transport
175
182
  (rate limit exhausted, 5xx, network fault) raises its `TransportError` subclass; either way the
176
- Conductor records a terminal trace event and commits nothing, rather than crashing or acting on a
177
- partial result. Treating the model as untrusted compute
178
- means a flaky reasoner can never produce a half-applied effect.
183
+ Conductor records a terminal trace event and stops subsequent work. Earlier effects remain real
184
+ and are reported in `RunResult.effects`; `committed=None` means no final value, not rollback.
179
185
  - **Capability composition (§5.4)**: every reasoner is bound to a `CapabilitySet`; the kernel rejects a
180
186
  reasoner whose grant exceeds the dispatcher's — a child can never widen authority. A `SubKernelStep`
181
187
  delegates untrusted content to an inner kernel at a **clamped, reduced grant**: an injection in that
@@ -184,9 +190,9 @@ result = kernel.run(ctx) # RunResult(trace, committed); committed is
184
190
  - **Static, data-independent control flow**: a `Plan` is a forward-only DAG of five step kinds
185
191
  (`const`, `tool`, `q_parse`, `subkernel`, `merge`), executed linearly by `kernel/interpreter.py`; a
186
192
  `QuarantineParseStep`'s target schema is fixed at plan time
187
- (`schema_ref`), never chosen on the quarantined value. No branch, loop, or tool selection is
188
- conditioned on untrusted content — so control-flow leaks of quarantined data are precluded by
189
- construction, not by policy (the matching cost is in *Honest limits*).
193
+ (`schema_ref`), never chosen on the quarantined value. There are no runtime branches or loops.
194
+ Delegated sub-planners can choose a child plan based on untrusted input; its authority and literal
195
+ provenance are reduced accordingly. This is not a claim of data-independent planning across delegation.
190
196
 
191
197
  ## Honest limits (fundamental — localized, not dissolved)
192
198
 
@@ -224,7 +230,7 @@ result = kernel.run(ctx) # RunResult(trace, committed); committed is
224
230
  - **Join** — combining values combines their labels conservatively (union of sources, intersection of
225
231
  readers, union of subjects), so taint only ever increases.
226
232
  - **Quarantine** — routing untrusted content through the Q-LLM, which cannot launder its taint.
227
- - **Capability / grant** — an unforgeable permission a tool requires; a run holds a fixed
233
+ - **Capability / grant** — a host-issued permission a tool requires; a run holds a fixed
228
234
  `CapabilitySet` (its *grant*), and a sub-kernel's grant can only ever shrink.
229
235
  - **Declassifier (`DeclassPolicy`)** — the single deterministic seam that may let tainted data into a
230
236
  WRITE; the one place trust is deliberately relaxed.
@@ -13,6 +13,10 @@ In particular (see the "Honest limits" section of the [README](README.md)):
13
13
  - A pass-through declassifier conforms to the pattern yet protects nothing — **the declassifier is the
14
14
  residual risk surface**. Every `may_declassify=True` is a deliberate, traced trust decision.
15
15
  - There is no atomicity / rollback: an effect already committed is real even if a later step fails.
16
+ - Operational sessions require explicit egress declarations and record uncertain effects; audit
17
+ storage failures halt work but cannot undo an external call. See [operations](docs/OPERATIONS.md).
18
+ - Providers are data recipients authorized by the host. Quarantine does not enforce confidentiality
19
+ against the selected provider. SQLite audit is not tamper-proof or a substitute for host access control.
16
20
 
17
21
  So a "vulnerability" here means a way to make the **kernel itself** commit an effect that its Gate and
18
22
  labels should have blocked — i.e. a hole in the mechanism (`kernel/`, `schemas/`, `memory/`), not a
@@ -35,6 +39,8 @@ permissive policy written on top of it.
35
39
  | Version | Supported |
36
40
  |---------|-----------|
37
41
  | `0.4.x` | ✅ |
42
+ | `0.5.0rc2` | Current candidate; report issues, validate adapters before application use |
43
+ | `0.5.0rc1` | Superseded candidate; upgrade to the current candidate |
38
44
  | `< 0.4` | ❌ |
39
45
 
40
46
  ## Reporting a vulnerability
@@ -47,4 +53,4 @@ Please report privately — do **not** open a public issue for a suspected vulne
47
53
  Include a minimal reproduction (a plan + tool/policy setup that commits an effect that should have been
48
54
  blocked), the expected vs. actual behavior, and the affected version/commit. Expect an initial
49
55
  acknowledgement within a few days. As a single-maintainer reference project there is no formal SLA, but
50
- mechanism-level issues are taken seriously and will be addressed in a `0.4.x` patch.
56
+ mechanism-level issues are taken seriously and addressed in the applicable supported release line.