techrevati-runtime 0.1.0__tar.gz → 0.3.0.dev1__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 (131) hide show
  1. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/.github/ISSUE_TEMPLATE/feature.md +3 -3
  2. techrevati_runtime-0.3.0.dev1/.github/workflows/ci.yml +124 -0
  3. techrevati_runtime-0.3.0.dev1/.github/workflows/codeql.yml +42 -0
  4. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/.github/workflows/docs.yml +4 -1
  5. techrevati_runtime-0.3.0.dev1/.github/workflows/release.yml +108 -0
  6. techrevati_runtime-0.3.0.dev1/CHANGELOG.md +560 -0
  7. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/CODEOWNERS +6 -0
  8. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/CONTRIBUTING.md +63 -2
  9. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/PKG-INFO +8 -6
  10. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/README.md +5 -5
  11. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/SECURITY.md +22 -0
  12. techrevati_runtime-0.3.0.dev1/docs/api/checkpoint.md +9 -0
  13. techrevati_runtime-0.3.0.dev1/docs/api/governance.md +3 -0
  14. techrevati_runtime-0.3.0.dev1/docs/api/hooks.md +3 -0
  15. techrevati_runtime-0.3.0.dev1/docs/api/persistence.md +7 -0
  16. techrevati_runtime-0.3.0.dev1/docs/api/rate_limit.md +10 -0
  17. techrevati_runtime-0.3.0.dev1/docs/api/routing.md +9 -0
  18. techrevati_runtime-0.3.0.dev1/docs/api/scheduler.md +8 -0
  19. techrevati_runtime-0.3.0.dev1/docs/api/streaming.md +3 -0
  20. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/index.md +8 -1
  21. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/migrating-from-0.0.x.md +2 -2
  22. techrevati_runtime-0.3.0.dev1/docs/migrating-from-0.1.x.md +71 -0
  23. techrevati_runtime-0.3.0.dev1/docs/patterns/durability.md +96 -0
  24. techrevati_runtime-0.3.0.dev1/docs/patterns/governance.md +194 -0
  25. techrevati_runtime-0.3.0.dev1/docs/patterns/hooks.md +262 -0
  26. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/orchestrator.md +9 -10
  27. techrevati_runtime-0.3.0.dev1/docs/patterns/rate-limiting.md +85 -0
  28. techrevati_runtime-0.3.0.dev1/docs/patterns/routing.md +82 -0
  29. techrevati_runtime-0.3.0.dev1/docs/patterns/streaming.md +177 -0
  30. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/tutorials/end-to-end.md +3 -3
  31. techrevati_runtime-0.3.0.dev1/examples/durable_agent.py +85 -0
  32. techrevati_runtime-0.3.0.dev1/examples/parallel_tools.py +42 -0
  33. techrevati_runtime-0.3.0.dev1/examples/pricing.json +46 -0
  34. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/examples/tiny_agent.py +5 -5
  35. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/mkdocs.yml +16 -1
  36. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/pyproject.toml +3 -1
  37. techrevati_runtime-0.3.0.dev1/scripts/check_module_coverage.py +77 -0
  38. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/__init__.py +119 -1
  39. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/agent_events.py +54 -0
  40. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/checkpoint.py +356 -0
  41. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/governance.py +259 -0
  42. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/guardrails.py +433 -0
  43. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/handoffs.py +2 -2
  44. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/hooks.py +515 -0
  45. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/orchestrator.py +565 -26
  46. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/otel.py +308 -0
  47. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/persistence.py +169 -0
  48. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/policy_engine.py +21 -0
  49. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/rate_limit.py +310 -0
  50. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/retry_policy.py +123 -37
  51. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/routing.py +180 -0
  52. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/scheduler.py +142 -0
  53. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/streaming.py +118 -0
  54. techrevati_runtime-0.3.0.dev1/src/techrevati/runtime/usage_tracking.py +424 -0
  55. techrevati_runtime-0.3.0.dev1/tests/conftest.py +23 -0
  56. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_async_circuit_breaker.py +1 -13
  57. techrevati_runtime-0.3.0.dev1/tests/test_async_guardrails.py +122 -0
  58. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_async_orchestrator.py +13 -13
  59. techrevati_runtime-0.3.0.dev1/tests/test_checkpoint.py +377 -0
  60. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_circuit_breaker.py +1 -13
  61. techrevati_runtime-0.3.0.dev1/tests/test_deprecation_warnings.py +66 -0
  62. techrevati_runtime-0.3.0.dev1/tests/test_governance.py +152 -0
  63. techrevati_runtime-0.3.0.dev1/tests/test_governance_events.py +101 -0
  64. techrevati_runtime-0.3.0.dev1/tests/test_governance_integration.py +200 -0
  65. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_guardrails.py +48 -11
  66. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_handoffs.py +5 -5
  67. techrevati_runtime-0.3.0.dev1/tests/test_hooks.py +422 -0
  68. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_max_iterations.py +7 -8
  69. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_orchestrator.py +18 -18
  70. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_otel.py +4 -4
  71. techrevati_runtime-0.3.0.dev1/tests/test_otel_atexit_cleanup.py +108 -0
  72. techrevati_runtime-0.3.0.dev1/tests/test_otel_nesting.py +141 -0
  73. techrevati_runtime-0.3.0.dev1/tests/test_pattern_and_prompt_injection_guardrails.py +153 -0
  74. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_permissions.py +39 -0
  75. techrevati_runtime-0.3.0.dev1/tests/test_property_circuit_breaker.py +112 -0
  76. techrevati_runtime-0.3.0.dev1/tests/test_property_retry_policy.py +150 -0
  77. techrevati_runtime-0.3.0.dev1/tests/test_rate_limit.py +237 -0
  78. techrevati_runtime-0.3.0.dev1/tests/test_register_pricing_on_conflict.py +69 -0
  79. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_retry_policy.py +3 -3
  80. techrevati_runtime-0.3.0.dev1/tests/test_routing.py +78 -0
  81. techrevati_runtime-0.3.0.dev1/tests/test_s0_regressions.py +245 -0
  82. techrevati_runtime-0.3.0.dev1/tests/test_s5_scheduler_persistence_async_policy.py +175 -0
  83. techrevati_runtime-0.3.0.dev1/tests/test_s5_usage_limits_and_caching.py +179 -0
  84. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_sinks.py +6 -6
  85. techrevati_runtime-0.3.0.dev1/tests/test_step_retries.py +115 -0
  86. techrevati_runtime-0.3.0.dev1/tests/test_streaming.py +263 -0
  87. techrevati_runtime-0.3.0.dev1/tests/test_taskgroup_parallel_tools.py +84 -0
  88. techrevati_runtime-0.1.0/.github/workflows/ci.yml +0 -72
  89. techrevati_runtime-0.1.0/.github/workflows/release.yml +0 -38
  90. techrevati_runtime-0.1.0/CHANGELOG.md +0 -219
  91. techrevati_runtime-0.1.0/examples/pricing.json +0 -37
  92. techrevati_runtime-0.1.0/src/techrevati/runtime/guardrails.py +0 -138
  93. techrevati_runtime-0.1.0/src/techrevati/runtime/otel.py +0 -190
  94. techrevati_runtime-0.1.0/src/techrevati/runtime/usage_tracking.py +0 -232
  95. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  96. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/.github/dependabot.yml +0 -0
  97. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/.gitignore +0 -0
  98. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/.pre-commit-config.yaml +0 -0
  99. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/LICENSE +0 -0
  100. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/circuit_breaker.md +0 -0
  101. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/guardrails.md +0 -0
  102. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/handoffs.md +0 -0
  103. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/orchestrator.md +0 -0
  104. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/otel.md +0 -0
  105. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/retry_policy.md +0 -0
  106. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/sinks.md +0 -0
  107. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/api/usage_tracking.md +0 -0
  108. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/changelog.md +0 -0
  109. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/getting-started.md +0 -0
  110. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/agent-events.md +0 -0
  111. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/circuit-breaker.md +0 -0
  112. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/lifecycle.md +0 -0
  113. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/permissions.md +0 -0
  114. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/policy.md +0 -0
  115. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/quality-gate.md +0 -0
  116. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/retry.md +0 -0
  117. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/docs/patterns/usage-tracking.md +0 -0
  118. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/__init__.py +0 -0
  119. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/agent_lifecycle.py +0 -0
  120. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/circuit_breaker.py +0 -0
  121. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/data/pricing.json +0 -0
  122. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/permissions.py +0 -0
  123. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/py.typed +0 -0
  124. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/quality_gate.py +0 -0
  125. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/src/techrevati/runtime/sinks.py +0 -0
  126. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/__init__.py +0 -0
  127. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_agent_events.py +0 -0
  128. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_agent_lifecycle.py +0 -0
  129. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_policy_engine.py +0 -0
  130. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_quality_gate.py +0 -0
  131. {techrevati_runtime-0.1.0 → techrevati_runtime-0.3.0.dev1}/tests/test_usage_tracking.py +0 -0
@@ -20,6 +20,6 @@ labels: enhancement
20
20
  <!-- What would you do today as a workaround? Why doesn't it scale? -->
21
21
 
22
22
  **Industry priors**
23
- <!-- Has another agent SDK (OpenAI Agents SDK, LangGraph, Anthropic
24
- Claude Agent SDK, etc.) shipped something similar? Link it. We
25
- prefer landing primitives that match industry conventions. -->
23
+ <!-- Has another agent SDK (OpenAI Agents SDK, LangGraph, etc.)
24
+ shipped something similar? Link it. We prefer landing
25
+ primitives that match industry conventions. -->
@@ -0,0 +1,124 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test on Python ${{ matrix.python-version }}
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ['3.11', '3.12', '3.13']
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+ cache: pip
25
+ cache-dependency-path: pyproject.toml
26
+
27
+ - name: Install package + dev dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ pip install -e ".[dev]"
31
+
32
+ - name: Lint with ruff
33
+ run: ruff check src/ tests/
34
+
35
+ - name: Format check with ruff
36
+ run: ruff format --check src/ tests/
37
+
38
+ - name: Type check with mypy
39
+ run: mypy src/ --strict
40
+
41
+ - name: Run tests
42
+ run: pytest tests/ -v --cov=src/techrevati --cov-report=term-missing --cov-report=xml
43
+
44
+ - name: Per-module coverage floor (>= 85%)
45
+ run: python scripts/check_module_coverage.py --threshold 85
46
+
47
+ - name: Upload coverage
48
+ uses: codecov/codecov-action@v4
49
+ with:
50
+ files: ./coverage.xml
51
+ fail_ci_if_error: false
52
+
53
+ build:
54
+ name: Build on Python ${{ matrix.python-version }}
55
+ runs-on: ubuntu-latest
56
+ needs: test
57
+ strategy:
58
+ matrix:
59
+ python-version: ['3.11', '3.12', '3.13']
60
+
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+
64
+ - name: Set up Python ${{ matrix.python-version }}
65
+ uses: actions/setup-python@v5
66
+ with:
67
+ python-version: ${{ matrix.python-version }}
68
+
69
+ - name: Install build tools
70
+ run: pip install build
71
+
72
+ - name: Build distribution
73
+ run: python -m build
74
+
75
+ - name: Check wheel
76
+ run: |
77
+ pip install dist/*.whl
78
+ python -c "from techrevati import runtime; print(f'techrevati-runtime {runtime.__version__}')"
79
+
80
+ zero-deps-smoke:
81
+ name: Zero-deps smoke on Python ${{ matrix.python-version }}
82
+ runs-on: ubuntu-latest
83
+ needs: build
84
+ strategy:
85
+ matrix:
86
+ python-version: ['3.11', '3.12', '3.13']
87
+
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+
91
+ - name: Set up Python ${{ matrix.python-version }}
92
+ uses: actions/setup-python@v5
93
+ with:
94
+ python-version: ${{ matrix.python-version }}
95
+
96
+ - name: Build distribution
97
+ run: |
98
+ pip install build
99
+ python -m build
100
+
101
+ - name: Install in an empty venv (no [dev], no [otel])
102
+ # Spin a fresh venv to verify the zero-runtime-dependency
103
+ # promise: the wheel must import with only stdlib + the wheel
104
+ # itself, no optional extras pulled in.
105
+ run: |
106
+ python -m venv smoke-venv
107
+ smoke-venv/bin/pip install --upgrade pip
108
+ smoke-venv/bin/pip install dist/*.whl
109
+ smoke-venv/bin/python -c "
110
+ import techrevati.runtime as r
111
+ assert r.__version__, '__version__ missing'
112
+ # Touch the public exports to make sure every module imports
113
+ # without optional deps installed.
114
+ from techrevati.runtime import (
115
+ AgentSession, OrchestrationSession, AsyncOrchestrationSession,
116
+ CircuitBreaker, AsyncCircuitBreaker,
117
+ TokenBucket, AsyncTokenBucket, RateLimiter,
118
+ StaticProviderRouter, RoundRobinProviderRouter,
119
+ InMemorySaver, SqliteSaver,
120
+ SqliteEventSink, SqliteUsageSink,
121
+ UsageLimits, ManualClock, SystemClock,
122
+ )
123
+ print(f'zero-deps smoke OK on techrevati-runtime {r.__version__}')
124
+ "
@@ -0,0 +1,42 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ # Weekly scan on Mondays — catches dependency-driven advisories
10
+ # that land after a PR has already been merged.
11
+ - cron: '0 6 * * 1'
12
+
13
+ permissions:
14
+ actions: read
15
+ contents: read
16
+ security-events: write
17
+
18
+ jobs:
19
+ analyze:
20
+ name: Analyze ${{ matrix.language }}
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ language: [python]
26
+
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - name: Initialize CodeQL
31
+ uses: github/codeql-action/init@v3
32
+ with:
33
+ languages: ${{ matrix.language }}
34
+ queries: security-and-quality
35
+
36
+ - name: Autobuild
37
+ uses: github/codeql-action/autobuild@v3
38
+
39
+ - name: Perform CodeQL Analysis
40
+ uses: github/codeql-action/analyze@v3
41
+ with:
42
+ category: "/language:${{ matrix.language }}"
@@ -26,7 +26,10 @@ jobs:
26
26
  pip install mkdocs mkdocs-material mkdocstrings[python]
27
27
 
28
28
  - name: Build documentation
29
- run: mkdocs build
29
+ # --strict turns broken refs and unresolved nav entries into
30
+ # hard failures so a doc regression cannot silently degrade
31
+ # the published site.
32
+ run: mkdocs build --strict
30
33
 
31
34
  - name: Deploy to GitHub Pages
32
35
  uses: peaceiris/actions-gh-pages@v3
@@ -0,0 +1,108 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ # contents: write so softprops/action-gh-release can create the
10
+ # GitHub Release; id-token: write for PyPI trusted publishing.
11
+ contents: write
12
+ id-token: write
13
+
14
+ jobs:
15
+ # Gate the release behind the same lint/type/test checks CI enforces
16
+ # on `main`. Without this, a tag push could publish a broken wheel to
17
+ # PyPI even if CI was red on the underlying commit. Matrix mirrors
18
+ # ci.yml so the gate has the same shape.
19
+ verify:
20
+ name: Verify on Python ${{ matrix.python-version }}
21
+ runs-on: ubuntu-latest
22
+ strategy:
23
+ matrix:
24
+ python-version: ['3.11', '3.12', '3.13']
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+
29
+ - name: Set up Python ${{ matrix.python-version }}
30
+ uses: actions/setup-python@v5
31
+ with:
32
+ python-version: ${{ matrix.python-version }}
33
+ cache: pip
34
+ cache-dependency-path: pyproject.toml
35
+
36
+ - name: Install package + dev dependencies
37
+ run: |
38
+ python -m pip install --upgrade pip
39
+ pip install -e ".[dev]"
40
+
41
+ - name: Lint with ruff
42
+ run: ruff check src/ tests/
43
+
44
+ - name: Format check with ruff
45
+ run: ruff format --check src/ tests/
46
+
47
+ - name: Type check with mypy
48
+ run: mypy src/ --strict
49
+
50
+ - name: Run tests
51
+ run: pytest tests/ -v --cov=src/techrevati --cov-report=term-missing
52
+
53
+ - name: Per-module coverage floor (>= 85%)
54
+ run: python scripts/check_module_coverage.py --threshold 85
55
+
56
+ release:
57
+ name: Release to PyPI
58
+ runs-on: ubuntu-latest
59
+ needs: verify
60
+
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+
64
+ - name: Set up Python
65
+ uses: actions/setup-python@v5
66
+ with:
67
+ python-version: '3.11'
68
+
69
+ - name: Install build tools
70
+ # cyclonedx-py is dev-only here — it generates the SBOM
71
+ # artifact and never touches the runtime install.
72
+ run: pip install build cyclonedx-bom
73
+
74
+ - name: Build distribution
75
+ run: python -m build
76
+
77
+ - name: Stage artifacts for PyPI
78
+ # Keep PyPI uploads strictly to wheel + sdist. The SBOM lives
79
+ # alongside the wheel on the GitHub Release but never lands on
80
+ # the index.
81
+ run: |
82
+ mkdir -p pypi-dist
83
+ cp dist/*.whl dist/*.tar.gz pypi-dist/
84
+
85
+ - name: Generate CycloneDX SBOM
86
+ # SBOM describes the build's dependency graph at publish time.
87
+ # PyPI's trusted-publishing attestations + this SBOM together
88
+ # give downstream consumers everything they need to verify
89
+ # provenance (see SECURITY.md for the verify command).
90
+ run: |
91
+ pip install dist/*.whl
92
+ cyclonedx-py environment --output-format json --output-file dist/sbom.cyclonedx.json
93
+ cyclonedx-py environment --output-format xml --output-file dist/sbom.cyclonedx.xml
94
+
95
+ - name: Publish to PyPI (Trusted Publishing)
96
+ uses: pypa/gh-action-pypi-publish@release/v1
97
+ with:
98
+ packages-dir: pypi-dist
99
+
100
+ - name: Create GitHub Release
101
+ uses: softprops/action-gh-release@v1
102
+ with:
103
+ generate_release_notes: true
104
+ files: |
105
+ dist/*.whl
106
+ dist/*.tar.gz
107
+ dist/sbom.cyclonedx.json
108
+ dist/sbom.cyclonedx.xml