toolframe-core 0.6.3__tar.gz → 0.6.4__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 (162) hide show
  1. toolframe_core-0.6.4/.github/dependabot.yml +50 -0
  2. toolframe_core-0.6.4/.github/workflows/ci.yml +52 -0
  3. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.github/workflows/container.yml +10 -2
  4. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.github/workflows/launcher.yml +3 -0
  5. toolframe_core-0.6.4/.github/workflows/pr-policy.yml +31 -0
  6. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.github/workflows/publish.yml +57 -28
  7. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.github/workflows/quality.yml +9 -23
  8. toolframe_core-0.6.4/.github/workflows/validate.yml +214 -0
  9. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/CHANGELOG.md +7 -0
  10. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/CONTRIBUTING.md +5 -5
  11. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/Cargo.lock +1 -1
  12. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/Cargo.toml +1 -1
  13. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/Dockerfile +2 -2
  14. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/PKG-INFO +1 -1
  15. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/architecture.md +3 -0
  16. toolframe_core-0.6.4/docs/artifacts.md +73 -0
  17. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/ci.md +59 -8
  18. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/container.md +5 -5
  19. toolframe_core-0.6.4/docs/intel-companion.md +100 -0
  20. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/postgresql-state.md +1 -1
  21. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/releasing.md +24 -13
  22. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/pyproject.toml +1 -1
  23. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/build-launcher.py +10 -11
  24. toolframe_core-0.6.4/scripts/ci/artifacts.py +496 -0
  25. toolframe_core-0.6.4/scripts/ci/intel-companion.json +29 -0
  26. toolframe_core-0.6.4/scripts/ci/intel_companion.py +365 -0
  27. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/ci/prepare-launcher.py +2 -1
  28. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/ci/validate.py +2 -1
  29. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/main.rs +8 -8
  30. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/__init__.py +1 -1
  31. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/host.py +3 -1
  32. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_acceptance.py +40 -0
  33. toolframe_core-0.6.4/tests/test_ci_artifacts.py +563 -0
  34. toolframe_core-0.6.4/tests/test_intel_companion.py +314 -0
  35. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_mcp_auth.py +4 -3
  36. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/uv.lock +1 -1
  37. toolframe_core-0.6.3/.github/dependabot.yml +0 -27
  38. toolframe_core-0.6.3/.github/workflows/ci.yml +0 -20
  39. toolframe_core-0.6.3/.github/workflows/validate.yml +0 -102
  40. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.dockerignore +0 -0
  41. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.github/actions/scan-container/action.yml +0 -0
  42. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.github/workflows/container-security.yml +0 -0
  43. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.gitignore +0 -0
  44. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/.pre-commit-config.yaml +0 -0
  45. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/LICENSE +0 -0
  46. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/NOTICE +0 -0
  47. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/README.md +0 -0
  48. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/cchk.toml +0 -0
  49. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/companion-wheels.txt +0 -0
  50. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0001-explicit-dashboard-access-mode.md +0 -0
  51. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0002-scoped-passwords-and-public-business-entrances.md +0 -0
  52. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0003-public-fallback-on-auth-error-or-disablement.md +0 -0
  53. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0004-separate-auth-ownership-from-dashboard-presentation.md +0 -0
  54. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0005-password-only-login-and-secret-reuse.md +0 -0
  55. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0006-require-explicit-plugin-authorization-contracts.md +0 -0
  56. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0007-independent-mcp-bearer-authentication.md +0 -0
  57. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0008-shared-oidc-authentication.md +0 -0
  58. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0009-replaceable-core-journal.md +0 -0
  59. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0010-multiple-sql-providers.md +0 -0
  60. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0011-safe-new-application-access.md +0 -0
  61. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0012-optional-runtime-tracing.md +0 -0
  62. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/adr/0013-context-logging.md +0 -0
  63. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/authentication.md +0 -0
  64. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/dependency-graph.md +0 -0
  65. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/glossary.md +0 -0
  66. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/mcp-authentication.md +0 -0
  67. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/object-storage.md +0 -0
  68. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/offline-maintenance.md +0 -0
  69. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/oidc-authentication.md +0 -0
  70. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/runtime.md +0 -0
  71. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/sql-storage.md +0 -0
  72. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/testing.md +0 -0
  73. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/docs/tracing.md +0 -0
  74. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/packaging/launcher/NOTICE +0 -0
  75. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/packaging/launcher/README.md +0 -0
  76. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/packaging/launcher/pyproject.toml +0 -0
  77. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/build-release.sh +0 -0
  78. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/check-container-security.py +0 -0
  79. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/check_branch_name.py +0 -0
  80. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/ci/check-launcher-wheel.py +0 -0
  81. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/ci/check-postgres.py +0 -0
  82. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/ci/check-release.py +0 -0
  83. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/ci/dependencies.json +0 -0
  84. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/container-healthcheck.py +0 -0
  85. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/dev-wheelhouse.sh +0 -0
  86. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/harden-container.py +0 -0
  87. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/prepare-container.py +0 -0
  88. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-auth-upgrade.py +0 -0
  89. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-auth.py +0 -0
  90. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-container.py +0 -0
  91. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-dependencies.py +0 -0
  92. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-network.py +0 -0
  93. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-operation-history.py +0 -0
  94. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-release.py +0 -0
  95. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-retained-plugins.py +0 -0
  96. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-scaffold.py +0 -0
  97. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/scripts/verify-skill.py +0 -0
  98. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/companions.rs +0 -0
  99. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/_state_postgres.py +0 -0
  100. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/_state_sqlite.py +0 -0
  101. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/access.py +0 -0
  102. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/api.py +0 -0
  103. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/LICENSE +0 -0
  104. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/SKILL.md +0 -0
  105. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/agents/openai.yaml +0 -0
  106. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/LICENSE +0 -0
  107. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/pyproject.toml +0 -0
  108. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/__init__.py +0 -0
  109. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/docs/usage.md +0 -0
  110. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/migrations/0001_init.sql +0 -0
  111. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/page.py +0 -0
  112. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/plugin.py +0 -0
  113. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/assets/sample-plugin/src/toolframe_sample_notes/service.py +0 -0
  114. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/evals/cases.json +0 -0
  115. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/design.md +0 -0
  116. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/operations.md +0 -0
  117. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/bundled_skills/toolframe-plugin-design/references/plugin-api.md +0 -0
  118. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/cli.py +0 -0
  119. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/config.py +0 -0
  120. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/diagnostics.py +0 -0
  121. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/graph.py +0 -0
  122. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/maintenance.py +0 -0
  123. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/mcp_access.py +0 -0
  124. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/network.py +0 -0
  125. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/oidc_access.py +0 -0
  126. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/packages.py +0 -0
  127. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/process.py +0 -0
  128. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/redaction.py +0 -0
  129. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/scaffold.py +0 -0
  130. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/skills.py +0 -0
  131. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/state.py +0 -0
  132. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/state_admin.py +0 -0
  133. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/stores.py +0 -0
  134. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/templates.json +0 -0
  135. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/toolframe_core/templates.py +0 -0
  136. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/src/uv.rs +0 -0
  137. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_access_policy.py +0 -0
  138. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_architecture.py +0 -0
  139. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_auth.py +0 -0
  140. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_bundles.py +0 -0
  141. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_cli.py +0 -0
  142. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_container_release.py +0 -0
  143. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_container_security.py +0 -0
  144. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_core_state.py +0 -0
  145. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_diagnostics.py +0 -0
  146. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_foundations.py +0 -0
  147. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_host.py +0 -0
  148. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_maintenance.py +0 -0
  149. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_managed_tasks.py +0 -0
  150. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_mixed_storage.py +0 -0
  151. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_network.py +0 -0
  152. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_object_store.py +0 -0
  153. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_oidc.py +0 -0
  154. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_operation_history.py +0 -0
  155. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_process.py +0 -0
  156. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_redaction.py +0 -0
  157. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_retained_plugins.py +0 -0
  158. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_scaffold.py +0 -0
  159. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_skills.py +0 -0
  160. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_storage_bindings.py +0 -0
  161. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/tests/test_tracing.py +0 -0
  162. {toolframe_core-0.6.3 → toolframe_core-0.6.4}/uv-release-manifest.txt +0 -0
@@ -0,0 +1,50 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: docker
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ time: '04:23'
9
+ timezone: Etc/UTC
10
+ open-pull-requests-limit: 4
11
+ commit-message:
12
+ prefix: fix(container)
13
+ pull-request-branch-name:
14
+ prefix: chore
15
+ template: '{prefix}/{name}'
16
+ groups:
17
+ # Catch every version and security update, including major versions.
18
+ # To split a dependency out, add a named group before these catch-alls;
19
+ # exclusions would fall back to noncompliant solo dependency/version names.
20
+ container-dependencies:
21
+ applies-to: version-updates
22
+ patterns: ['*']
23
+ container-security:
24
+ applies-to: security-updates
25
+ patterns: ['*']
26
+ ignore:
27
+ # The 0.6.3 launcher accepts uv >=0.12.2,<0.13.0.
28
+ # Widen this only alongside a compatible launcher release.
29
+ - dependency-name: astral-sh/uv
30
+ versions: ['>=0.13.0']
31
+ - package-ecosystem: github-actions
32
+ directory: /
33
+ schedule:
34
+ interval: weekly
35
+ day: monday
36
+ time: '04:23'
37
+ timezone: Etc/UTC
38
+ open-pull-requests-limit: 4
39
+ commit-message:
40
+ prefix: chore(ci)
41
+ pull-request-branch-name:
42
+ prefix: chore
43
+ template: '{prefix}/{name}'
44
+ groups:
45
+ actions-dependencies:
46
+ applies-to: version-updates
47
+ patterns: ['*']
48
+ actions-security:
49
+ applies-to: security-updates
50
+ patterns: ['*']
@@ -0,0 +1,52 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ # Publication independently verifies/promotes the selected release tag.
7
+ branches: [main]
8
+ workflow_dispatch:
9
+ inputs:
10
+ rebuild:
11
+ description: Run all checks and builds even if validated artifacts exist
12
+ type: boolean
13
+ default: false
14
+
15
+ permissions:
16
+ contents: read
17
+ pull-requests: read
18
+ actions: read
19
+
20
+ concurrency:
21
+ group: ci-${{ github.workflow }}-${{ github.ref }}
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ quality:
26
+ uses: ./.github/workflows/quality.yml
27
+
28
+ validate:
29
+ needs: quality
30
+ uses: ./.github/workflows/validate.yml
31
+ with:
32
+ reuse-stage: ${{ github.ref == 'refs/heads/main' && 'main' || 'none' }}
33
+ rebuild: ${{ inputs.rebuild || false }}
34
+ secrets: inherit
35
+
36
+ result:
37
+ name: CI result
38
+ if: always()
39
+ needs: [quality, validate]
40
+ runs-on: ubuntu-24.04
41
+ timeout-minutes: 2
42
+ steps:
43
+ # Require this check when configuring branch protection. A skipped
44
+ # validation job must not turn a failed prerequisite into a green check.
45
+ - name: Require successful checks and validation
46
+ env:
47
+ QUALITY_RESULT: ${{ needs.quality.result }}
48
+ VALIDATE_RESULT: ${{ needs.validate.result }}
49
+ run: |
50
+ echo "Quality: $QUALITY_RESULT; validation: $VALIDATE_RESULT"
51
+ test "$QUALITY_RESULT" = success
52
+ test "$VALIDATE_RESULT" = success
@@ -79,8 +79,16 @@ jobs:
79
79
  if: inputs.release_artifacts
80
80
  uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
81
81
  with:
82
- name: launcher-release-${{ matrix.target }}
83
- path: build/container-release/
82
+ name: validated-release
83
+ path: build/candidate/
84
+ - name: Verify the bundle and stage this platform's release
85
+ if: inputs.release_artifacts
86
+ env:
87
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
88
+ TOOLFRAME_TARGET: ${{ matrix.target }}
89
+ run: >-
90
+ python scripts/ci/artifacts.py export --bundle build/candidate
91
+ --kind release --target "$TOOLFRAME_TARGET" --output build/container-release
84
92
  - name: Stage the verified executable
85
93
  env:
86
94
  USE_ARTIFACTS: ${{ inputs.release_artifacts }}
@@ -76,6 +76,7 @@ jobs:
76
76
  name: launcher-wheel-${{ matrix.target }}
77
77
  path: build/launcher-dist/wheels/*.whl
78
78
  if-no-files-found: error
79
+ overwrite: true
79
80
  retention-days: 14
80
81
  - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
81
82
  with:
@@ -86,6 +87,7 @@ jobs:
86
87
  build/launcher-dist/release/*.json
87
88
  build/launcher-dist/release/SHA256SUMS-*.txt
88
89
  if-no-files-found: error
90
+ overwrite: true
89
91
  retention-days: 14
90
92
  - name: Retain acceptance evidence
91
93
  if: always()
@@ -94,3 +96,4 @@ jobs:
94
96
  name: launcher-evidence-${{ matrix.target }}
95
97
  path: build/launcher-dist/*.json
96
98
  if-no-files-found: warn
99
+ overwrite: true
@@ -0,0 +1,31 @@
1
+ name: Pull request policy
2
+
3
+ on:
4
+ workflow_call:
5
+ # Keep a stable required check for title edits without repeating native CI.
6
+ pull_request:
7
+ types: [opened, synchronize, reopened, edited]
8
+
9
+ permissions:
10
+ contents: read
11
+ pull-requests: read
12
+
13
+ jobs:
14
+ commit-policy:
15
+ name: PR policy
16
+ runs-on: ubuntu-24.04
17
+ timeout-minutes: 10
18
+ steps:
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
20
+ with:
21
+ fetch-depth: 0
22
+ persist-credentials: false
23
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
24
+ with:
25
+ python-version: '3.14.7'
26
+ - uses: commit-check/commit-check-action@a61779784a953fd9047c001c102cfeac5cf26964 # commit-check 2.18.3
27
+ with:
28
+ message: true
29
+ branch: false
30
+ pr-title: true
31
+ pr-comments: false
@@ -11,9 +11,15 @@ on:
11
11
  - pypi
12
12
  default: testpypi
13
13
  required: true
14
+ rebuild:
15
+ description: Validate and rebuild at the tag instead of promoting main artifacts
16
+ type: boolean
17
+ default: false
14
18
 
15
19
  permissions:
16
20
  contents: read
21
+ actions: read
22
+ pull-requests: read
17
23
 
18
24
  concurrency:
19
25
  group: publish-${{ github.ref }}-${{ inputs.index }}
@@ -33,9 +39,19 @@ jobs:
33
39
  - name: Require the exact project version tag
34
40
  run: python scripts/ci/check-release.py --ref "$GITHUB_REF"
35
41
 
36
- validate:
42
+ quality:
37
43
  needs: release-tag
44
+ permissions:
45
+ contents: read
46
+ pull-requests: read
47
+ uses: ./.github/workflows/quality.yml
48
+
49
+ validate:
50
+ needs: [release-tag, quality]
38
51
  uses: ./.github/workflows/validate.yml
52
+ with:
53
+ reuse-stage: release
54
+ rebuild: ${{ inputs.rebuild }}
39
55
  secrets: inherit
40
56
 
41
57
  publish-core:
@@ -45,22 +61,24 @@ jobs:
45
61
  environment:
46
62
  name: ${{ inputs.index }}
47
63
  permissions:
64
+ contents: read
48
65
  id-token: write
49
66
  steps:
50
- - name: Download the distributions validated in this run
67
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
68
+ with:
69
+ persist-credentials: false
70
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
71
+ with:
72
+ python-version: '3.14.7'
73
+ - name: Download the bundle validated in this run
51
74
  uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
52
75
  with:
53
- name: python-dist
54
- path: dist/
55
- - name: Require the complete Core release set
56
- run: |
57
- python - <<'PY'
58
- from pathlib import Path
59
- files = list(Path('dist').iterdir())
60
- assert len(list(Path('dist').glob('toolframe_core-*.whl'))) == 1
61
- assert len(list(Path('dist').glob('toolframe_core-*.tar.gz'))) == 1
62
- assert len(files) == 2
63
- PY
76
+ name: validated-release
77
+ path: build/candidate/
78
+ - name: Verify and stage the exact Core distributions
79
+ env:
80
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
81
+ run: python scripts/ci/artifacts.py export --bundle build/candidate --kind core --output dist
64
82
  - name: Publish Core using its Trusted Publisher
65
83
  uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
66
84
  with:
@@ -74,22 +92,24 @@ jobs:
74
92
  environment:
75
93
  name: ${{ inputs.index }}-launcher
76
94
  permissions:
95
+ contents: read
77
96
  id-token: write
78
97
  steps:
79
- - name: Download all four validated native wheels
98
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
99
+ with:
100
+ persist-credentials: false
101
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
102
+ with:
103
+ python-version: '3.14.7'
104
+ - name: Download the bundle validated in this run
80
105
  uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
81
106
  with:
82
- pattern: launcher-wheel-*
83
- merge-multiple: true
84
- path: dist/
85
- - name: Require the complete launcher release set
86
- run: |
87
- python - <<'PY'
88
- from pathlib import Path
89
- files = list(Path('dist').iterdir())
90
- assert len(list(Path('dist').glob('toolframe-*.whl'))) == 4
91
- assert len(files) == 4
92
- PY
107
+ name: validated-release
108
+ path: build/candidate/
109
+ - name: Verify and stage all four exact native wheels
110
+ env:
111
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
112
+ run: python scripts/ci/artifacts.py export --bundle build/candidate --kind wheel --output dist
93
113
  - name: Publish the launcher using its Trusted Publisher
94
114
  uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
95
115
  with:
@@ -104,11 +124,20 @@ jobs:
104
124
  permissions:
105
125
  contents: write
106
126
  steps:
127
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
128
+ with:
129
+ persist-credentials: false
130
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
131
+ with:
132
+ python-version: '3.14.7'
107
133
  - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
108
134
  with:
109
- pattern: launcher-release-*
110
- merge-multiple: true
111
- path: releases/
135
+ name: validated-release
136
+ path: build/candidate/
137
+ - name: Verify and stage the exact release archives
138
+ env:
139
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
140
+ run: python scripts/ci/artifacts.py export --bundle build/candidate --kind release --output releases
112
141
  - name: Publish verified executables and checksums
113
142
  env:
114
143
  GH_TOKEN: ${{ github.token }}
@@ -1,11 +1,7 @@
1
1
  name: Code quality
2
2
 
3
3
  on:
4
- push:
5
- branches: ['**']
6
- pull_request:
7
- types: [opened, synchronize, reopened, edited]
8
- workflow_dispatch:
4
+ workflow_call:
9
5
 
10
6
  permissions:
11
7
  contents: read
@@ -21,10 +17,15 @@ jobs:
21
17
  - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
22
18
  with:
23
19
  python-version: '3.14.7'
24
- - name: Check the actual source branch
20
+ - name: Check the source branch or selected release tag
25
21
  env:
26
22
  BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
27
- run: python scripts/check_branch_name.py "$BRANCH_NAME"
23
+ run: |
24
+ if [ "$GITHUB_REF_TYPE" = tag ]; then
25
+ python scripts/ci/check-release.py --ref "$GITHUB_REF"
26
+ else
27
+ python scripts/check_branch_name.py "$BRANCH_NAME"
28
+ fi
28
29
 
29
30
  code-quality:
30
31
  runs-on: ubuntu-24.04
@@ -42,22 +43,7 @@ jobs:
42
43
 
43
44
  commit-policy:
44
45
  if: github.event_name == 'pull_request'
45
- runs-on: ubuntu-24.04
46
- timeout-minutes: 10
47
46
  permissions:
48
47
  contents: read
49
48
  pull-requests: read
50
- steps:
51
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
52
- with:
53
- fetch-depth: 0
54
- persist-credentials: false
55
- - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
56
- with:
57
- python-version: '3.14.7'
58
- - uses: commit-check/commit-check-action@a61779784a953fd9047c001c102cfeac5cf26964 # commit-check 2.18.3
59
- with:
60
- message: true
61
- branch: false
62
- pr-title: true
63
- pr-comments: false
49
+ uses: ./.github/workflows/pr-policy.yml
@@ -0,0 +1,214 @@
1
+ name: Validate distributions and launchers
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ reuse-stage:
7
+ type: string
8
+ default: none
9
+ rebuild:
10
+ type: boolean
11
+ default: false
12
+
13
+ permissions:
14
+ contents: read
15
+ actions: read
16
+ pull-requests: read
17
+
18
+ # Concurrency belongs to the caller: a reusable workflow must not cancel it.
19
+ jobs:
20
+ reuse:
21
+ name: Resolve validated artifacts
22
+ runs-on: ubuntu-24.04
23
+ timeout-minutes: 10
24
+ outputs:
25
+ reused: ${{ steps.resolve.outputs.reused }}
26
+ steps:
27
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
28
+ with:
29
+ persist-credentials: false
30
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
31
+ with:
32
+ python-version: '3.14.7'
33
+ - name: Verify the source run, complete bundle and checksums
34
+ id: resolve
35
+ env:
36
+ GH_TOKEN: ${{ github.token }}
37
+ REUSE_STAGE: ${{ inputs.reuse-stage }}
38
+ REBUILD: ${{ inputs.rebuild }}
39
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
40
+ run: |
41
+ options=()
42
+ if [ "$REBUILD" = true ]; then options+=(--rebuild); fi
43
+ python scripts/ci/artifacts.py resolve --stage "$REUSE_STAGE" \
44
+ --output build/candidate "${options[@]}"
45
+ - name: Retain the promoted bytes and their provenance
46
+ if: steps.resolve.outputs.reused == 'true'
47
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
48
+ with:
49
+ name: validated-release
50
+ path: build/candidate/
51
+ if-no-files-found: error
52
+ overwrite: true
53
+ retention-days: 30
54
+
55
+ postgres:
56
+ needs: reuse
57
+ if: needs.reuse.outputs.reused == 'false'
58
+ name: PostgreSQL journal and mixed SQL storage
59
+ runs-on: ubuntu-latest
60
+ timeout-minutes: 20
61
+ services:
62
+ postgres:
63
+ image: postgres:16.14-alpine
64
+ env:
65
+ POSTGRES_USER: postgres
66
+ POSTGRES_PASSWORD: postgres
67
+ ports:
68
+ - 5432:5432
69
+ options: >-
70
+ --health-cmd "pg_isready -U postgres"
71
+ --health-interval 5s --health-timeout 5s --health-retries 10
72
+ env:
73
+ TOOLFRAME_CORE_TEST_ADMIN_DSN: postgresql://postgres:postgres@127.0.0.1:5432/postgres
74
+ TOOLFRAME_POSTGRES_PG_DUMP: /usr/lib/postgresql/16/bin/pg_dump
75
+ TOOLFRAME_POSTGRES_PG_RESTORE: /usr/lib/postgresql/16/bin/pg_restore
76
+ TOOLFRAME_REPOSITORY_TOKEN: ${{ secrets.TOOLFRAME_READ_TOKEN }}
77
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
78
+ steps:
79
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
80
+ with:
81
+ persist-credentials: false
82
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
83
+ with:
84
+ python-version: '3.14.7'
85
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
86
+ with:
87
+ version: '0.12.8'
88
+ enable-cache: false
89
+ - name: Install matching PostgreSQL backup tools
90
+ run: sudo apt-get update && sudo apt-get install -y postgresql-client-16
91
+ - name: Verify journals, mixed storage and failure recovery
92
+ run: >-
93
+ python scripts/ci/validate.py --checks postgres --output build/ci-postgres
94
+ --repository-owner "$TOOLFRAME_REPOSITORY_OWNER"
95
+ - name: Save PostgreSQL validation evidence
96
+ if: always()
97
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
98
+ with:
99
+ name: postgres-validation
100
+ path: |
101
+ build/ci-postgres/*.json
102
+ build/ci-postgres/workspace.txt
103
+ if-no-files-found: warn
104
+ overwrite: true
105
+ python:
106
+ needs: reuse
107
+ if: needs.reuse.outputs.reused == 'false'
108
+ name: Python integration and distribution
109
+ runs-on: macos-15
110
+ timeout-minutes: 40
111
+ env:
112
+ # github.repository_owner is the base repository owner, including fork PRs.
113
+ TOOLFRAME_REPOSITORY_TOKEN: ${{ secrets.TOOLFRAME_READ_TOKEN }}
114
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
115
+ steps:
116
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
117
+ with:
118
+ persist-credentials: false
119
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
120
+ with:
121
+ python-version: '3.14.7'
122
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
123
+ with:
124
+ version: '0.12.8'
125
+ enable-cache: false
126
+ - name: Validate in a fresh pinned workspace
127
+ run: >-
128
+ python scripts/ci/validate.py --checks python --output build/ci-python
129
+ --repository-owner "$TOOLFRAME_REPOSITORY_OWNER"
130
+ - name: Save validated Python distributions
131
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
132
+ with:
133
+ name: python-dist
134
+ path: build/ci-python/python-dist/
135
+ if-no-files-found: error
136
+ overwrite: true
137
+ retention-days: 14
138
+ - name: Save Python validation evidence
139
+ if: always()
140
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
141
+ with:
142
+ name: python-validation
143
+ path: |
144
+ build/ci-python/*.json
145
+ build/ci-python/*.xml
146
+ build/ci-python/workspace.txt
147
+ if-no-files-found: warn
148
+ overwrite: true
149
+ retention-days: 14
150
+
151
+ launcher:
152
+ needs: reuse
153
+ if: needs.reuse.outputs.reused == 'false'
154
+ uses: ./.github/workflows/launcher.yml
155
+ secrets: inherit
156
+
157
+ bundle:
158
+ name: Seal complete validation
159
+ needs: [reuse, python, postgres, launcher]
160
+ if: >-
161
+ always() && needs.reuse.result == 'success' &&
162
+ needs.reuse.outputs.reused == 'false' &&
163
+ needs.python.result == 'success' && needs.postgres.result == 'success' &&
164
+ needs.launcher.result == 'success'
165
+ runs-on: ubuntu-24.04
166
+ timeout-minutes: 10
167
+ steps:
168
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
169
+ with:
170
+ persist-credentials: false
171
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
172
+ with:
173
+ python-version: '3.14.7'
174
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
175
+ with:
176
+ pattern: '{python-dist,python-validation,postgres-validation,launcher-*}'
177
+ path: build/candidate/
178
+ - name: Seal distributions and installed-application evidence
179
+ env:
180
+ TOOLFRAME_REPOSITORY_OWNER: ${{ vars.TOOLFRAME_REPOSITORY_OWNER || github.repository_owner }}
181
+ run: python scripts/ci/artifacts.py seal --bundle build/candidate
182
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
183
+ with:
184
+ name: validated-release
185
+ path: build/candidate/
186
+ if-no-files-found: error
187
+ overwrite: true
188
+ retention-days: 30
189
+
190
+ result:
191
+ name: Validated artifacts
192
+ if: always()
193
+ needs: [reuse, python, postgres, launcher, bundle]
194
+ runs-on: ubuntu-24.04
195
+ timeout-minutes: 2
196
+ steps:
197
+ - name: Require verified reuse or complete fresh validation
198
+ env:
199
+ REUSE_RESULT: ${{ needs.reuse.result }}
200
+ REUSED: ${{ needs.reuse.outputs.reused }}
201
+ PYTHON_RESULT: ${{ needs.python.result }}
202
+ POSTGRES_RESULT: ${{ needs.postgres.result }}
203
+ LAUNCHER_RESULT: ${{ needs.launcher.result }}
204
+ BUNDLE_RESULT: ${{ needs.bundle.result }}
205
+ run: |
206
+ test "$REUSE_RESULT" = success
207
+ case "$REUSED" in
208
+ true) expected=skipped ;;
209
+ false) expected=success ;;
210
+ *) exit 1 ;;
211
+ esac
212
+ for result in "$PYTHON_RESULT" "$POSTGRES_RESULT" "$LAUNCHER_RESULT" "$BUNDLE_RESULT"; do
213
+ test "$result" = "$expected"
214
+ done
@@ -5,6 +5,13 @@ imply that its distributions have been published or every target is qualified.
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 0.6.4
9
+
10
+ - Refresh the container runtime packages to include Debian
11
+ `libexpat1 2.9.0-1~deb13u1`, fixing six Expat security advisories in
12
+ the standard image. Both image variants retain the existing vulnerability
13
+ publication policy.
14
+
8
15
  ## 0.6.3
9
16
 
10
17
  - Apply container security updates, remove unused pip bootstrap dependencies and
@@ -25,8 +25,8 @@ prek run --all-files
25
25
  The Ruff version and checked paths are pinned in
26
26
  [the hook configuration](.pre-commit-config.yaml); the Python rules remain in
27
27
  [pyproject.toml](pyproject.toml). CI uses these same hooks on all tracked files
28
- within their configured paths. Existing package, integration, and release checks
29
- run independently.
28
+ within their configured paths. Package, integration, and release validation starts
29
+ after the quality checks pass; see [CI checks](docs/ci.md).
30
30
 
31
31
  ## Branches and commits
32
32
 
@@ -42,6 +42,6 @@ Commits with its default subject length of 5–80 characters. Pull requests chec
42
42
  their commits and title so the title can be used for a Conventional Commit when
43
43
  squash merging.
44
44
 
45
- Local hooks can be bypassed. CI reports `branch-policy`, `code-quality`, and
46
- `commit-policy`; maintainers must configure required status checks separately to
47
- make passing checks a merge requirement.
45
+ Local hooks can be bypassed. Configure `CI result` and the standalone `PR policy`
46
+ as required status checks to enforce source validation and PR title/commit policy.
47
+ The [CI guide](docs/ci.md) describes their triggers and gating behavior.
@@ -1186,7 +1186,7 @@ dependencies = [
1186
1186
 
1187
1187
  [[package]]
1188
1188
  name = "toolframe"
1189
- version = "0.6.3"
1189
+ version = "0.6.4"
1190
1190
  dependencies = [
1191
1191
  "anyhow",
1192
1192
  "flate2",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "toolframe"
3
- version = "0.6.3"
3
+ version = "0.6.4"
4
4
  edition = "2024"
5
5
  rust-version = "1.88"
6
6
  description = "A local-first runtime for agent-built internal apps"
@@ -3,7 +3,7 @@ FROM ghcr.io/astral-sh/uv:0.12.24@sha256:3af4716e991d6956a41e573eab705d0ee08500c
3
3
 
4
4
  FROM debian:trixie-slim@sha256:a29215f6a35e51e22adffa17f89e9d2ef06214e64a2bad10d765c46aea49f11f AS runtime
5
5
  ARG TARGETARCH
6
- ARG TOOLFRAME_VERSION=0.6.3
6
+ ARG TOOLFRAME_VERSION=0.6.4
7
7
  ARG TOOLFRAME_REVISION
8
8
  LABEL org.opencontainers.image.source="https://github.com/toolframe/toolframe-core" \
9
9
  org.opencontainers.image.title="Toolframe" \
@@ -68,7 +68,7 @@ RUN mkdir -p /opt/ps-libs/var/lib/dpkg/status.d \
68
68
  && dpkg-query -s tini > /opt/ps-libs/var/lib/dpkg/status.d/tini
69
69
 
70
70
  FROM gcr.io/distroless/cc-debian13:nonroot@sha256:e792ab3d241a468a4fd7519ddbbebe66b49b5f365771716ea688ad40b6c6f1c2 AS distroless
71
- ARG TOOLFRAME_VERSION=0.6.3
71
+ ARG TOOLFRAME_VERSION=0.6.4
72
72
  ARG TOOLFRAME_REVISION
73
73
  LABEL org.opencontainers.image.source="https://github.com/toolframe/toolframe-core" \
74
74
  org.opencontainers.image.title="Toolframe (Distroless)" \
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: toolframe-core
3
- Version: 0.6.3
3
+ Version: 0.6.4
4
4
  Summary: Persistent control host for isolated Toolframe plugins
5
5
  Project-URL: Homepage, https://github.com/toolframe/toolframe-core
6
6
  Project-URL: Repository, https://github.com/toolframe/toolframe-core
@@ -155,6 +155,9 @@ Plugins declare owned pages, tools and documents. Providers prepare a complete
155
155
  catalog, then acknowledge the selected epoch before Core makes their entrance
156
156
  available. A failed acknowledgement remains a visible unavailable entrance;
157
157
  publication is not presented as a distributed atomic transaction.
158
+ Each publication consumes health changes already included in its snapshot, so a
159
+ completed reload does not trigger another cutover for the same failure. Health
160
+ changes observed while that snapshot is being published schedule another update.
158
161
 
159
162
  Native Streamlit pages call business services through the SDK page bridge. MCP
160
163
  tools declare schemas and target business methods; the provider does not import