capability-reasoning-kernel 0.4.2__tar.gz → 0.5.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.
Files changed (112) hide show
  1. capability_reasoning_kernel-0.5.0/.github/dependabot.yml +13 -0
  2. capability_reasoning_kernel-0.5.0/.github/workflows/ci.yml +151 -0
  3. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/.github/workflows/pages.yml +4 -4
  4. capability_reasoning_kernel-0.5.0/.github/workflows/release.yml +107 -0
  5. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/.pre-commit-config.yaml +2 -2
  6. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/CHANGELOG.md +74 -0
  7. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/PKG-INFO +36 -23
  8. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/README.md +24 -18
  9. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/SECURITY.md +7 -1
  10. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/docs/ANALYSIS-2026-07.md +3 -0
  11. capability_reasoning_kernel-0.5.0/docs/CONFORMANCE.md +30 -0
  12. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/docs/DEVELOPMENT.md +26 -8
  13. capability_reasoning_kernel-0.5.0/docs/OPERATIONS.md +149 -0
  14. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/docs/index.html +6 -6
  15. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/justfile +10 -4
  16. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/pyproject.toml +10 -4
  17. capability_reasoning_kernel-0.5.0/scripts/check_artifacts.py +46 -0
  18. capability_reasoning_kernel-0.5.0/scripts/check_published.py +57 -0
  19. capability_reasoning_kernel-0.5.0/scripts/check_version.py +15 -0
  20. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/__init__.py +28 -3
  21. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/kernel/effects.py +175 -0
  22. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/kernel/gate.py +139 -0
  23. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/kernel/interpreter.py +118 -64
  24. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/kernel/runtime.py +63 -0
  25. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/kernel/session.py +61 -0
  26. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/memory/sink.py +212 -0
  27. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/memory/trace.py +150 -0
  28. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/anthropic.py +14 -3
  29. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/base.py +53 -2
  30. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/deepseek.py +4 -0
  31. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/openai.py +69 -30
  32. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/parse.py +11 -3
  33. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/reasoner/telemetry.py +36 -0
  34. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/capability.py +1 -1
  35. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/schemas/limits.py +36 -0
  36. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/registry.py +4 -1
  37. capability_reasoning_kernel-0.5.0/src/reasoning_kernel/schemas/trace.py +184 -0
  38. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/tools/demo_mail.py +6 -3
  39. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/tools/registry.py +6 -0
  40. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_interpreter_loop.py +4 -2
  41. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_no_bypass_conformance.py +7 -3
  42. capability_reasoning_kernel-0.5.0/tests/test_operational.py +729 -0
  43. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_parse_with_schema.py +24 -1
  44. capability_reasoning_kernel-0.5.0/tests/test_provider_contracts.py +170 -0
  45. capability_reasoning_kernel-0.5.0/tests/test_providers_live.py +183 -0
  46. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_reasoner_robustness.py +3 -3
  47. capability_reasoning_kernel-0.5.0/tests/test_release_contract.py +88 -0
  48. capability_reasoning_kernel-0.5.0/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.0}/.env.example +0 -0
  59. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/.gitignore +0 -0
  60. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/.python-version +0 -0
  61. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/CLAUDE.md +0 -0
  62. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/LICENSE +0 -0
  63. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/docs/.nojekyll +0 -0
  64. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/docs/favicon.svg +0 -0
  65. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/config.py +0 -0
  66. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/context/__init__.py +0 -0
  67. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/context/assembler.py +0 -0
  68. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/__init__.py +0 -0
  69. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/_report.py +0 -0
  70. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/email_exfil.py +0 -0
  71. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/live_run.py +0 -0
  72. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/merge.py +0 -0
  73. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/reasoner_error.py +0 -0
  74. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/run_limits.py +0 -0
  75. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/demo/subkernel.py +0 -0
  76. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/kernel/__init__.py +0 -0
  77. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/kernel/taint.py +0 -0
  78. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/memory/__init__.py +0 -0
  79. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/memory/store.py +0 -0
  80. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/py.typed +0 -0
  81. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/__init__.py +0 -0
  82. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/factory.py +0 -0
  83. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/fake.py +0 -0
  84. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/reasoner/roles.py +0 -0
  85. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/__init__.py +0 -0
  86. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/ids.py +0 -0
  87. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/plan.py +0 -0
  88. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/policy.py +0 -0
  89. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/provenance.py +0 -0
  90. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/schemas/values.py +0 -0
  91. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/src/reasoning_kernel/tools/__init__.py +0 -0
  92. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/conftest.py +0 -0
  93. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_capability.py +0 -0
  94. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_composition.py +0 -0
  95. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_declass_policy.py +0 -0
  96. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_demo_email_exfil.py +0 -0
  97. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_demo_mail_tools.py +0 -0
  98. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_gate_capability.py +0 -0
  99. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_gate_provenance_declassify.py +0 -0
  100. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_gate_unrestricted_readers.py +0 -0
  101. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_invariant_a.py +0 -0
  102. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_merge.py +0 -0
  103. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_plan_schema.py +0 -0
  104. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_provenance_propagation.py +0 -0
  105. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_public_api.py +0 -0
  106. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_reasoner_factory.py +0 -0
  107. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_registry.py +0 -0
  108. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_run_limits.py +0 -0
  109. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_store.py +0 -0
  110. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_subject_provenance.py +0 -0
  111. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/tests/test_subkernel.py +0 -0
  112. {capability_reasoning_kernel-0.4.2 → capability_reasoning_kernel-0.5.0}/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@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
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@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
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@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
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,20 +29,20 @@ 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
 
41
41
  - name: Upload artifact
42
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
42
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
43
43
  with:
44
44
  path: docs
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@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
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,77 @@ 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.0] - 2026-09-06
8
+
9
+ First stable operational embedding release. It promotes the two release candidates after package,
10
+ provider and real-consumer compatibility validation; each host remains responsible for validating
11
+ its own live adapters and policies.
12
+
13
+ ### Changed
14
+
15
+ - Qualify OpenAI SDK 3.8 through the required live DeepSeek compatibility gate without calling the
16
+ OpenAI service, and update the locked Pyright version.
17
+ - Upgrade the SHA-pinned uv and Pages actions after CI artifact round-trip and rendered Pages checks.
18
+ - Validate Vibemonitor's real `KernelGate` integration and complete consumer suite on Python 3.14.
19
+
20
+ ## [0.5.0rc2] - 2026-09-06
21
+
22
+ Maintenance candidate following the first published operational release. Publication remains
23
+ separate from live host-adapter acceptance.
24
+
25
+ ### Added
26
+
27
+ - SQLite audit discovery for reserved run IDs and runs needing operator review after incomplete or
28
+ uncertain execution.
29
+
30
+ ### Changed
31
+
32
+ - Validate the provider adapters against OpenAI SDK 3.7 and Anthropic SDK 1.4, while bounding their
33
+ optional dependency ranges below the next untested major versions.
34
+ - Upgrade SHA-pinned GitHub Actions and add a CI upload/download checksum round trip for release
35
+ artifacts; group future Actions updates into one Dependabot pull request.
36
+ - Refresh the locked Pydantic, pytest and ruff versions used by CI and local development.
37
+
38
+ ### Fixed
39
+
40
+ - Package builds clear stale distributions, while published-artifact verification ignores unrelated
41
+ files and still requires exactly one wheel and one source distribution.
42
+
43
+ ## [0.5.0rc1] - 2026-09-06
44
+
45
+ Published operational embedding candidate. Publication does not imply live-adapter UAT.
46
+
47
+ ### Added
48
+
49
+ - Single-use `RunSession`, bounded operational defaults and root-wide step/tool/parser/LLM budgets.
50
+ - Explicit tool egress declarations, normalized input verification and output model revalidation.
51
+ - `TraceSink`, memory/SQLite sinks, durable pre-call records and fail-closed storage handling.
52
+ - Correlated invocation IDs, parent run IDs, partial/uncertain effect outcomes and terminal run status.
53
+ - Redacted operational events, detached snapshots and canonical detailed digests.
54
+ - Bounded shared reasoner executor, returned usage/latency capture and public provider result types.
55
+ - Sanitized provider failure categories, HTTP status and allow-listed operational error codes.
56
+ - Crash, concurrency, shared-budget, adapter-contract and provider failure regression tests.
57
+ - Python 3.14 CI, locked dependencies, pinned actions and single-artifact release promotion with
58
+ a pinned/checksummed uv runtime, version checks, isolated wheel smoke and served-byte verification.
59
+ - Operational/migration guide and conformance checklist.
60
+
61
+ ### Changed
62
+
63
+ - Require a patched `pydantic-settings>=2.14.2` (GHSA-4xgf-cpjx-pc3j) and refresh its lock entry.
64
+ - Version the SQLite audit schema, migrate the unversioned candidate layout, reject unknown/newer
65
+ layouts or missing key constraints, and verify released bytes after TestPyPI and PyPI publication.
66
+ - Require an explicit live-provider set in release CI; `0.5.0rc1` qualifies DeepSeek while OpenAI
67
+ remains supported but is not live-qualified for this candidate.
68
+ - Low-level interpreters reject reuse and context/trace mismatches; child IDs are opaque.
69
+ - Limits span descendants; `RunLimits()` remains unbounded for explicit low-level wiring.
70
+ - Failed tools stop later steps without implying rollback; output validation cannot undo a call.
71
+ - OpenAI-compatible fallback uses structured error parameters, once; refusals/truncations and
72
+ malformed outputs are terminal errors. DeepSeek routes directly through JSON mode with local
73
+ schema validation because its compatible API does not implement OpenAI's native JSON Schema mode.
74
+ Provider exception messages no longer include raw API text.
75
+ - Pyright explicitly resolves the project virtualenv. Documentation distinguishes root planning,
76
+ delegated untrusted planning and partial effects.
77
+
7
78
  ## [0.4.2] - 2026-07-10
8
79
 
9
80
  A correctness release for the gate's provenance stage, plus fail-closed hardening of the provider
@@ -143,6 +214,9 @@ Initial reference implementation of the Reasoning Kernel pattern (strong / CaMeL
143
214
  invariants, no-effect-bypasses-the-Verifier by construction, the deterministic declassification seam,
144
215
  and the worked email-exfiltration demo.
145
216
 
217
+ [0.5.0]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.5.0
218
+ [0.5.0rc2]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.5.0rc2
219
+ [0.5.0rc1]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.5.0rc1
146
220
  [0.4.2]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.4.2
147
221
  [0.4.1]: https://github.com/gianlucamazza/reasoning-kernel/releases/tag/v0.4.1
148
222
  [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.0
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 release explicitly with
161
+ `pip install capability-reasoning-kernel==0.5.0`.
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. Package publication and
166
+ consumer compatibility tests are not evidence that a host's live adapters are correctly configured.
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 release explicitly with
122
+ `pip install capability-reasoning-kernel==0.5.0`.
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. Package publication and
127
+ consumer compatibility tests are not evidence that a host's live adapters are correctly configured.
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.