ragops 2.2.0__tar.gz → 2.3.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 (271) hide show
  1. {ragops-2.2.0 → ragops-2.3.0}/.github/ISSUE_TEMPLATE/bug.yml +1 -1
  2. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/ragops-gate.yml +1 -1
  3. {ragops-2.2.0 → ragops-2.3.0}/CHANGELOG.md +14 -0
  4. {ragops-2.2.0 → ragops-2.3.0}/PKG-INFO +3 -3
  5. {ragops-2.2.0 → ragops-2.3.0}/README.md +2 -2
  6. ragops-2.3.0/docs/architecture/adr/0020-local-release-integrity.md +17 -0
  7. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/cv-linkedin-copy.md +1 -1
  8. ragops-2.3.0/docs/design-audit/v2.3/01-workbench-desktop.png +0 -0
  9. ragops-2.3.0/docs/design-audit/v2.3/audit.md +20 -0
  10. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/github-pr-gate.md +1 -1
  11. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/gitlab-ci-gate.md +1 -1
  12. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/pypi-publishing.md +3 -3
  13. {ragops-2.2.0 → ragops-2.3.0}/docs/examples/gitlab-ci-ragops.yml +1 -1
  14. ragops-2.3.0/docs/product/requirements-v2.3.md +24 -0
  15. {ragops-2.2.0 → ragops-2.3.0}/docs/product/roadmap.md +12 -1
  16. {ragops-2.2.0 → ragops-2.3.0}/docs/product/success-metrics.md +7 -1
  17. {ragops-2.2.0 → ragops-2.3.0}/docs/project/program-completion-audit.md +5 -2
  18. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v2.2-acceptance.md +6 -5
  19. ragops-2.3.0/docs/project/v2.3-acceptance.md +30 -0
  20. ragops-2.3.0/docs/releases/v2.3.0.md +22 -0
  21. {ragops-2.2.0 → ragops-2.3.0}/pyproject.toml +1 -1
  22. {ragops-2.2.0 → ragops-2.3.0}/scripts/local_release.py +37 -1
  23. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/__init__.py +1 -1
  24. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/cli.py +2 -0
  25. {ragops-2.2.0 → ragops-2.3.0}/tests/test_adoption_recipes.py +1 -1
  26. {ragops-2.2.0 → ragops-2.3.0}/tests/test_local_release.py +25 -0
  27. {ragops-2.2.0 → ragops-2.3.0}/tests/test_public_api.py +12 -1
  28. {ragops-2.2.0 → ragops-2.3.0}/.dockerignore +0 -0
  29. {ragops-2.2.0 → ragops-2.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  30. {ragops-2.2.0 → ragops-2.3.0}/.github/ISSUE_TEMPLATE/design-partner.yml +0 -0
  31. {ragops-2.2.0 → ragops-2.3.0}/.github/ISSUE_TEMPLATE/evaluator.yml +0 -0
  32. {ragops-2.2.0 → ragops-2.3.0}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
  33. {ragops-2.2.0 → ragops-2.3.0}/.github/pull_request_template.md +0 -0
  34. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/ci.yml +0 -0
  35. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/nightly.yml +0 -0
  36. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/pages.yml +0 -0
  37. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/publish-pypi.yml +0 -0
  38. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/ragops-gate-smoke.yml +0 -0
  39. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/ragops-pr-comment.yml +0 -0
  40. {ragops-2.2.0 → ragops-2.3.0}/.github/workflows/release.yml +0 -0
  41. {ragops-2.2.0 → ragops-2.3.0}/.gitignore +0 -0
  42. {ragops-2.2.0 → ragops-2.3.0}/AGENTS.md +0 -0
  43. {ragops-2.2.0 → ragops-2.3.0}/CODE_OF_CONDUCT.md +0 -0
  44. {ragops-2.2.0 → ragops-2.3.0}/CONTRIBUTING.md +0 -0
  45. {ragops-2.2.0 → ragops-2.3.0}/Dockerfile +0 -0
  46. {ragops-2.2.0 → ragops-2.3.0}/LICENSE +0 -0
  47. {ragops-2.2.0 → ragops-2.3.0}/NEXT_SESSION.md +0 -0
  48. {ragops-2.2.0 → ragops-2.3.0}/SECURITY.md +0 -0
  49. {ragops-2.2.0 → ragops-2.3.0}/SUPPORT.md +0 -0
  50. {ragops-2.2.0 → ragops-2.3.0}/apps/__init__.py +0 -0
  51. {ragops-2.2.0 → ragops-2.3.0}/apps/api/__init__.py +0 -0
  52. {ragops-2.2.0 → ragops-2.3.0}/apps/api/main.py +0 -0
  53. {ragops-2.2.0 → ragops-2.3.0}/apps/github_pr_comment.py +0 -0
  54. {ragops-2.2.0 → ragops-2.3.0}/apps/web/index.html +0 -0
  55. {ragops-2.2.0 → ragops-2.3.0}/compose.yaml +0 -0
  56. {ragops-2.2.0 → ragops-2.3.0}/design-qa.md +0 -0
  57. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0001-local-first-core.md +0 -0
  58. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0002-baseline-regression-gates.md +0 -0
  59. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0003-reference-app-outside-core.md +0 -0
  60. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0004-open-core-boundary.md +0 -0
  61. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0005-scenario-0.2-metadata-and-citation-precision.md +0 -0
  62. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0006-response-fixture-overlays.md +0 -0
  63. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0007-offline-reference-graphrag-agent.md +0 -0
  64. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0008-local-team-review-workflow.md +0 -0
  65. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0009-adopt-mit-license.md +0 -0
  66. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0010-repair-trace-04-schema-json.md +0 -0
  67. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0011-reusable-pr-gate-is-an-adapter.md +0 -0
  68. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0012-opentelemetry-export-is-an-example-adapter.md +0 -0
  69. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0013-additive-demo-catalog-and-codepoint-budget.md +0 -0
  70. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0014-separate-pr-evaluation-from-comment-publication.md +0 -0
  71. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0015-portable-design-partner-measurement.md +0 -0
  72. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0016-first-class-evaluator-gates.md +0 -0
  73. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0017-api-authentication-and-input-bounds.md +0 -0
  74. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0018-portable-external-metric-envelope.md +0 -0
  75. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/adr/0019-local-release-fallback.md +0 -0
  76. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/component-diagram.md +0 -0
  77. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/context-diagram.md +0 -0
  78. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/control-plane-alpha.md +0 -0
  79. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/data-model.md +0 -0
  80. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/pr-comment-publishing.md +0 -0
  81. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/system-overview.md +0 -0
  82. {ragops-2.2.0 → ragops-2.3.0}/docs/architecture/threat-model.md +0 -0
  83. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/design-audit/01-current-desktop.jpg +0 -0
  84. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/design-audit/02-implementation-desktop.jpg +0 -0
  85. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/design-audit/04-implementation-mobile.jpg +0 -0
  86. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/design-audit/06-desktop-comparison.jpg +0 -0
  87. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/design-audit/09-limitations-section.jpg +0 -0
  88. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/design-audit/selected-open-source-adoption.png +0 -0
  89. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/infographics/evidence-stack.svg +0 -0
  90. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/infographics/release-gate-flow.svg +0 -0
  91. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/portfolio-case-study.md +0 -0
  92. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/portfolio-handoff.md +0 -0
  93. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/presentation-outline.md +0 -0
  94. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/screenshots/ragops-limitations-screen.jpg +0 -0
  95. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/screenshots/ragops-mobile-screen.jpg +0 -0
  96. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/screenshots/ragops-portfolio-desktop.jpg +0 -0
  97. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/screenshots/ragops-portfolio-mobile.jpg +0 -0
  98. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/screenshots/ragops-release-screen.jpg +0 -0
  99. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/screenshots/ragops-showcase-hero.jpg +0 -0
  100. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/social-preview.png +0 -0
  101. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/video-script.md +0 -0
  102. {ragops-2.2.0 → ragops-2.3.0}/docs/demo/walkthrough.md +0 -0
  103. {ragops-2.2.0 → ragops-2.3.0}/docs/design-audit/v1.9/01-start.png +0 -0
  104. {ragops-2.2.0 → ragops-2.3.0}/docs/design-audit/v1.9/02-pass-decision.png +0 -0
  105. {ragops-2.2.0 → ragops-2.3.0}/docs/design-audit/v1.9/03-invalid-json-stale-decision.png +0 -0
  106. {ragops-2.2.0 → ragops-2.3.0}/docs/design-audit/v1.9/04-fixed-pass-decision.png +0 -0
  107. {ragops-2.2.0 → ragops-2.3.0}/docs/design-audit/v1.9/05-fixed-invalid-json.png +0 -0
  108. {ragops-2.2.0 → ragops-2.3.0}/docs/design-audit/v1.9/workbench-audit.md +0 -0
  109. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/export-your-first-trace.md +0 -0
  110. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/handbook.md +0 -0
  111. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/local-release.md +0 -0
  112. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/observability.md +0 -0
  113. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/provider-adapters.md +0 -0
  114. {ragops-2.2.0 → ragops-2.3.0}/docs/engineering/testing-strategy.md +0 -0
  115. {ragops-2.2.0 → ragops-2.3.0}/docs/evaluation/answer-length-budget.md +0 -0
  116. {ragops-2.2.0 → ragops-2.3.0}/docs/evaluation/benchmark-report-v0.2.md +0 -0
  117. {ragops-2.2.0 → ragops-2.3.0}/docs/evaluation/evaluator-gates.md +0 -0
  118. {ragops-2.2.0 → ragops-2.3.0}/docs/evaluation/red-team-plan.md +0 -0
  119. {ragops-2.2.0 → ragops-2.3.0}/docs/evaluation/scenario-taxonomy.md +0 -0
  120. {ragops-2.2.0 → ragops-2.3.0}/docs/evaluation/strategy.md +0 -0
  121. {ragops-2.2.0 → ragops-2.3.0}/docs/examples/github-pr-comment.yml +0 -0
  122. {ragops-2.2.0 → ragops-2.3.0}/docs/getting-started.md +0 -0
  123. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/design-partner-outreach.md +0 -0
  124. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/design-partner-pilot-runbook.md +0 -0
  125. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/github-launch-checklist.md +0 -0
  126. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/pilot-fixtures/synthetic-economics.json +0 -0
  127. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/pilot-fixtures/synthetic-manifest.json +0 -0
  128. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/pilot-fixtures/synthetic-observations.jsonl +0 -0
  129. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/pilot-measurement-plan.md +0 -0
  130. {ragops-2.2.0 → ragops-2.3.0}/docs/gtm/synthetic-pilot-report.md +0 -0
  131. {ragops-2.2.0 → ragops-2.3.0}/docs/product/commercialization.md +0 -0
  132. {ragops-2.2.0 → ragops-2.3.0}/docs/product/competitive-analysis.md +0 -0
  133. {ragops-2.2.0 → ragops-2.3.0}/docs/product/jobs-to-be-done.md +0 -0
  134. {ragops-2.2.0 → ragops-2.3.0}/docs/product/oss-launch-plan.md +0 -0
  135. {ragops-2.2.0 → ragops-2.3.0}/docs/product/personas.md +0 -0
  136. {ragops-2.2.0 → ragops-2.3.0}/docs/product/product_thesis.md +0 -0
  137. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v0.1.md +0 -0
  138. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v0.2.md +0 -0
  139. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v1.5.md +0 -0
  140. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v1.6.md +0 -0
  141. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v1.7.md +0 -0
  142. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v1.8.md +0 -0
  143. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v2.0.md +0 -0
  144. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v2.1.md +0 -0
  145. {ragops-2.2.0 → ragops-2.3.0}/docs/product/requirements-v2.2.md +0 -0
  146. {ragops-2.2.0 → ragops-2.3.0}/docs/project/backlog.md +0 -0
  147. {ragops-2.2.0 → ragops-2.3.0}/docs/project/charter.md +0 -0
  148. {ragops-2.2.0 → ragops-2.3.0}/docs/project/decision-log.md +0 -0
  149. {ragops-2.2.0 → ragops-2.3.0}/docs/project/m1-acceptance.md +0 -0
  150. {ragops-2.2.0 → ragops-2.3.0}/docs/project/m2-acceptance.md +0 -0
  151. {ragops-2.2.0 → ragops-2.3.0}/docs/project/m3-acceptance.md +0 -0
  152. {ragops-2.2.0 → ragops-2.3.0}/docs/project/m4-acceptance.md +0 -0
  153. {ragops-2.2.0 → ragops-2.3.0}/docs/project/m5-acceptance.md +0 -0
  154. {ragops-2.2.0 → ragops-2.3.0}/docs/project/milestones.md +0 -0
  155. {ragops-2.2.0 → ragops-2.3.0}/docs/project/release-plan.md +0 -0
  156. {ragops-2.2.0 → ragops-2.3.0}/docs/project/risk-register.md +0 -0
  157. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v1-acceptance.md +0 -0
  158. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v1.5-acceptance.md +0 -0
  159. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v1.6-acceptance.md +0 -0
  160. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v1.7-acceptance.md +0 -0
  161. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v1.8-acceptance.md +0 -0
  162. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v2.0-acceptance.md +0 -0
  163. {ragops-2.2.0 → ragops-2.3.0}/docs/project/v2.1-acceptance.md +0 -0
  164. {ragops-2.2.0 → ragops-2.3.0}/docs/project/work-breakdown.md +0 -0
  165. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v1.5.0.md +0 -0
  166. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v1.6.0.md +0 -0
  167. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v1.7.0.md +0 -0
  168. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v1.8.0.md +0 -0
  169. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v2.0.0.md +0 -0
  170. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v2.1.0.md +0 -0
  171. {ragops-2.2.0 → ragops-2.3.0}/docs/releases/v2.2.0.md +0 -0
  172. {ragops-2.2.0 → ragops-2.3.0}/examples/__init__.py +0 -0
  173. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/README.md +0 -0
  174. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/__init__.py +0 -0
  175. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/agent.py +0 -0
  176. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/architecture.md +0 -0
  177. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/cli.py +0 -0
  178. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/data/documents.json +0 -0
  179. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/data/graph.json +0 -0
  180. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/discovery.md +0 -0
  181. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/executive-report.md +0 -0
  182. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/results/comparison.md +0 -0
  183. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/results/graph-traces.jsonl +0 -0
  184. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/results/lexical-traces.jsonl +0 -0
  185. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/rollout-plan.md +0 -0
  186. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/scenario.json +0 -0
  187. {ragops-2.2.0 → ragops-2.3.0}/examples/japanese_troubleshooting_agent/suite.json +0 -0
  188. {ragops-2.2.0 → ragops-2.3.0}/examples/opentelemetry_trace_adapter/README.md +0 -0
  189. {ragops-2.2.0 → ragops-2.3.0}/examples/opentelemetry_trace_adapter/__init__.py +0 -0
  190. {ragops-2.2.0 → ragops-2.3.0}/examples/opentelemetry_trace_adapter/adapter.py +0 -0
  191. {ragops-2.2.0 → ragops-2.3.0}/examples/opentelemetry_trace_adapter/spans.jsonl +0 -0
  192. {ragops-2.2.0 → ragops-2.3.0}/ragops.toml +0 -0
  193. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/attack-pack.json +0 -0
  194. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/benchmark-adversarial.json +0 -0
  195. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/benchmark-baseline.json +0 -0
  196. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/benchmark-regressed.json +0 -0
  197. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/benchmark-v0.2.json +0 -0
  198. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/evaluation-policy.toml +0 -0
  199. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/external-metric-policy.toml +0 -0
  200. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/external-metrics-baseline.json +0 -0
  201. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/external-metrics-candidate.json +0 -0
  202. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/regressed_responses.json +0 -0
  203. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/sample_responses.json +0 -0
  204. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/sample_traces.jsonl +0 -0
  205. {ragops-2.2.0 → ragops-2.3.0}/scenarios/japanese_troubleshooting/scenario.json +0 -0
  206. {ragops-2.2.0 → ragops-2.3.0}/schemas/attack-pack-0.1.schema.json +0 -0
  207. {ragops-2.2.0 → ragops-2.3.0}/schemas/external-metrics-0.1.schema.json +0 -0
  208. {ragops-2.2.0 → ragops-2.3.0}/schemas/pilot-economics-0.1.schema.json +0 -0
  209. {ragops-2.2.0 → ragops-2.3.0}/schemas/pilot-manifest-0.1.schema.json +0 -0
  210. {ragops-2.2.0 → ragops-2.3.0}/schemas/pilot-observation-0.1.schema.json +0 -0
  211. {ragops-2.2.0 → ragops-2.3.0}/schemas/report-0.2.schema.json +0 -0
  212. {ragops-2.2.0 → ragops-2.3.0}/schemas/response-fixture-0.2.schema.json +0 -0
  213. {ragops-2.2.0 → ragops-2.3.0}/schemas/responses-0.1.schema.json +0 -0
  214. {ragops-2.2.0 → ragops-2.3.0}/schemas/scenario-0.1.schema.json +0 -0
  215. {ragops-2.2.0 → ragops-2.3.0}/schemas/scenario-0.2.schema.json +0 -0
  216. {ragops-2.2.0 → ragops-2.3.0}/schemas/trace-0.3.schema.json +0 -0
  217. {ragops-2.2.0 → ragops-2.3.0}/schemas/trace-0.4.schema.json +0 -0
  218. {ragops-2.2.0 → ragops-2.3.0}/site/apple-touch-icon.png +0 -0
  219. {ragops-2.2.0 → ragops-2.3.0}/site/favicon.png +0 -0
  220. {ragops-2.2.0 → ragops-2.3.0}/site/index.html +0 -0
  221. {ragops-2.2.0 → ragops-2.3.0}/site/styles.css +0 -0
  222. {ragops-2.2.0 → ragops-2.3.0}/skills/ragops-feature/SKILL.md +0 -0
  223. {ragops-2.2.0 → ragops-2.3.0}/skills/ragops-presentation/SKILL.md +0 -0
  224. {ragops-2.2.0 → ragops-2.3.0}/skills/ragops-release/SKILL.md +0 -0
  225. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/adapters/__init__.py +0 -0
  226. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/adapters/external_metrics.py +0 -0
  227. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/adapters/http.py +0 -0
  228. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/benchmarks.py +0 -0
  229. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/config.py +0 -0
  230. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/control_plane.py +0 -0
  231. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/demo.py +0 -0
  232. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/engine.py +0 -0
  233. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/evaluators.py +0 -0
  234. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/loader.py +0 -0
  235. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/models.py +0 -0
  236. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/pilot.py +0 -0
  237. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/plugins.py +0 -0
  238. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/providers/__init__.py +0 -0
  239. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/providers/openai_responses.py +0 -0
  240. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/reporters.py +0 -0
  241. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/store.py +0 -0
  242. {ragops-2.2.0 → ragops-2.3.0}/src/ragops/traces.py +0 -0
  243. {ragops-2.2.0 → ragops-2.3.0}/tests/test_answer_length_cli.py +0 -0
  244. {ragops-2.2.0 → ragops-2.3.0}/tests/test_api_contract.py +0 -0
  245. {ragops-2.2.0 → ragops-2.3.0}/tests/test_benchmarks.py +0 -0
  246. {ragops-2.2.0 → ragops-2.3.0}/tests/test_comparison.py +0 -0
  247. {ragops-2.2.0 → ragops-2.3.0}/tests/test_config.py +0 -0
  248. {ragops-2.2.0 → ragops-2.3.0}/tests/test_control_plane.py +0 -0
  249. {ragops-2.2.0 → ragops-2.3.0}/tests/test_demo.py +0 -0
  250. {ragops-2.2.0 → ragops-2.3.0}/tests/test_engine.py +0 -0
  251. {ragops-2.2.0 → ragops-2.3.0}/tests/test_evaluator_depth.py +0 -0
  252. {ragops-2.2.0 → ragops-2.3.0}/tests/test_external_metrics.py +0 -0
  253. {ragops-2.2.0 → ragops-2.3.0}/tests/test_github_workflows.py +0 -0
  254. {ragops-2.2.0 → ragops-2.3.0}/tests/test_http_adapter.py +0 -0
  255. {ragops-2.2.0 → ragops-2.3.0}/tests/test_loader.py +0 -0
  256. {ragops-2.2.0 → ragops-2.3.0}/tests/test_openai_provider.py +0 -0
  257. {ragops-2.2.0 → ragops-2.3.0}/tests/test_opentelemetry_adapter.py +0 -0
  258. {ragops-2.2.0 → ragops-2.3.0}/tests/test_pilot.py +0 -0
  259. {ragops-2.2.0 → ragops-2.3.0}/tests/test_plugins_and_traces.py +0 -0
  260. {ragops-2.2.0 → ragops-2.3.0}/tests/test_pr_comment_publisher.py +0 -0
  261. {ragops-2.2.0 → ragops-2.3.0}/tests/test_readme_visuals.py +0 -0
  262. {ragops-2.2.0 → ragops-2.3.0}/tests/test_reference_agent.py +0 -0
  263. {ragops-2.2.0 → ragops-2.3.0}/tests/test_reference_benchmark.py +0 -0
  264. {ragops-2.2.0 → ragops-2.3.0}/tests/test_release_version.py +0 -0
  265. {ragops-2.2.0 → ragops-2.3.0}/tests/test_response_fixtures.py +0 -0
  266. {ragops-2.2.0 → ragops-2.3.0}/tests/test_scenario_v02_and_attacks.py +0 -0
  267. {ragops-2.2.0 → ragops-2.3.0}/tests/test_schema_files.py +0 -0
  268. {ragops-2.2.0 → ragops-2.3.0}/tests/test_showcase_site.py +0 -0
  269. {ragops-2.2.0 → ragops-2.3.0}/tests/test_store_and_html.py +0 -0
  270. {ragops-2.2.0 → ragops-2.3.0}/tests/test_team_workflow.py +0 -0
  271. {ragops-2.2.0 → ragops-2.3.0}/tests/test_workbench.py +0 -0
@@ -10,7 +10,7 @@ body:
10
10
  id: version
11
11
  attributes:
12
12
  label: RAGOps version or commit
13
- placeholder: v2.1.0 or commit SHA
13
+ placeholder: v2.3.0 or commit SHA
14
14
  validations:
15
15
  required: true
16
16
  - type: textarea
@@ -12,7 +12,7 @@ on:
12
12
  description: RAGOps Git revision or tag to install
13
13
  required: false
14
14
  type: string
15
- default: "v2.1.0"
15
+ default: "v2.3.0"
16
16
  scenario:
17
17
  description: Caller-relative scenario JSON path
18
18
  required: true
@@ -4,6 +4,20 @@ All notable changes follow Keep a Changelog. This project uses Semantic Versioni
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.3.0] - 2026-07-13
8
+
9
+ ### Added
10
+
11
+ - `ragops --version` for installed-package and support diagnostics.
12
+ - Clean-wheel installation smoke testing in the local release verification lane.
13
+
14
+ ### Changed
15
+
16
+ - Local artifact checksum verification is dependency-free and portable across
17
+ supported operating systems.
18
+ - Public documentation, roadmap, release evidence, and integration examples now
19
+ identify the current stable release consistently.
20
+
7
21
  ## [2.2.0] - 2026-07-13
8
22
 
9
23
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragops
3
- Version: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Evaluation and red-team release gates for RAG and agent systems
5
5
  Project-URL: Homepage, https://github.com/thangldw/ragops
6
6
  Project-URL: Documentation, https://github.com/thangldw/ragops#readme
@@ -94,7 +94,7 @@ ragops demo --output ragops-demo
94
94
  For the latest published stable CLI without cloning the repository:
95
95
 
96
96
  ```bash
97
- pip install ragops==2.1.0
97
+ pip install ragops==2.3.0
98
98
  ragops demo --output ragops-demo
99
99
  ```
100
100
 
@@ -136,7 +136,7 @@ validate the harness and architecture comparison; they do not establish
136
136
  Japanese semantic quality, customer adoption, or production ROI.
137
137
 
138
138
  The repository currently validates its core, adapters, reference deployment,
139
- showcase, and demo paths with 138 automated tests.
139
+ showcase, and demo paths with 140+ automated tests.
140
140
 
141
141
  <p align="center">
142
142
  <img src="docs/demo/infographics/evidence-stack.svg" alt="RAGOps evidence stack combining quality, safety, operational budgets, and regression comparison into a release decision" width="100%">
@@ -63,7 +63,7 @@ ragops demo --output ragops-demo
63
63
  For the latest published stable CLI without cloning the repository:
64
64
 
65
65
  ```bash
66
- pip install ragops==2.1.0
66
+ pip install ragops==2.3.0
67
67
  ragops demo --output ragops-demo
68
68
  ```
69
69
 
@@ -105,7 +105,7 @@ validate the harness and architecture comparison; they do not establish
105
105
  Japanese semantic quality, customer adoption, or production ROI.
106
106
 
107
107
  The repository currently validates its core, adapters, reference deployment,
108
- showcase, and demo paths with 138 automated tests.
108
+ showcase, and demo paths with 140+ automated tests.
109
109
 
110
110
  <p align="center">
111
111
  <img src="docs/demo/infographics/evidence-stack.svg" alt="RAGOps evidence stack combining quality, safety, operational budgets, and regression comparison into a release decision" width="100%">
@@ -0,0 +1,17 @@
1
+ # ADR 0020: Verify local release integrity before publication
2
+
3
+ Status: Accepted for owner review
4
+
5
+ ## Decision
6
+
7
+ The quota-independent release lane must install its newly built wheel in a fresh
8
+ virtual environment before publication. SHA-256 verification is implemented in
9
+ dependency-free Python rather than delegating to platform-specific `shasum` or
10
+ `sha256sum` commands. The installed CLI exposes its package version.
11
+
12
+ ## Consequences
13
+
14
+ Local releases catch missing-package and metadata errors before tags are pushed,
15
+ and PyPI promotion works consistently on macOS, Linux, and Windows. Verification
16
+ takes slightly longer because it creates an isolated environment. This does not
17
+ replace the supported-Python matrix when GitHub Actions capacity returns.
@@ -15,7 +15,7 @@ not customer production adoption.
15
15
  candidate with 25-point citation coverage/precision regressions. The fixture
16
16
  validates harness behavior, not Japanese semantic quality.
17
17
  - Published architecture decisions, threat model, rollout plan, executive
18
- go/no-go recommendation, reproducible reports, and 138 automated tests.
18
+ go/no-go recommendation, reproducible reports, and 140+ automated tests.
19
19
 
20
20
  ## LinkedIn project description
21
21
 
@@ -0,0 +1,20 @@
1
+ # v2.3 workbench product-flow audit
2
+
3
+ ## Flow
4
+
5
+ 1. **Evaluation input — healthy.** API key is explicitly tab-local; scenario and
6
+ response fixtures are prefilled and labeled.
7
+ 2. **Release decision — healthy empty state.** Before evaluation the UI says
8
+ “Waiting for a run” and “Not evaluated”; it does not display stale PASS data.
9
+ 3. **Experiment history — healthy with setup guidance.** The run limit is labeled
10
+ and the page explains the `RAGOPS_STORE` requirement.
11
+
12
+ ## Highest-impact follow-up
13
+
14
+ No release-blocking redesign is justified. A future usability study should test
15
+ whether adopters prefer file upload over large JSON textareas; screenshots alone
16
+ cannot establish this. Keyboard behavior, screen-reader announcements, focus
17
+ movement after evaluation, and color contrast require dedicated accessibility
18
+ testing and are not claimed here.
19
+
20
+ ![Workbench desktop](01-workbench-desktop.png)
@@ -22,7 +22,7 @@ jobs:
22
22
  release-gate:
23
23
  uses: thangldw/ragops/.github/workflows/ragops-gate.yml@main
24
24
  with:
25
- ragops-version: v2.1.0
25
+ ragops-version: v2.3.0
26
26
  scenario: evals/scenario.json
27
27
  baseline: evals/baseline.json
28
28
  candidate: evals/candidate.json
@@ -19,7 +19,7 @@ Set these repository-relative variables:
19
19
 
20
20
  ```yaml
21
21
  variables:
22
- RAGOPS_VERSION: "2.1.0"
22
+ RAGOPS_VERSION: "2.3.0"
23
23
  RAGOPS_SCENARIO: "evaluation/scenario.json"
24
24
  RAGOPS_BASELINE: "evaluation/baseline.json"
25
25
  RAGOPS_CANDIDATE: "evaluation/candidate.json"
@@ -9,10 +9,10 @@ PyPI API token and publishes only an existing tag whose `vX.Y.Z` value matches
9
9
 
10
10
  - Project: [ragops on PyPI](https://pypi.org/project/ragops/)
11
11
  - First Trusted Publishing release: `1.6.0`
12
- - Current verified release: `2.1.0`
12
+ - Current verified release: `2.2.0`
13
13
  - GitHub environment: `pypi`
14
14
  - Publisher: `thangldw/ragops`, workflow `publish-pypi.yml`
15
- - Verification: 2.1.0 wheel and sdist present; clean install and
15
+ - Verification: 2.2.0 wheel and sdist present; clean install and
16
16
  credential-free proposal-review demo pass
17
17
 
18
18
  ## One-time owner setup
@@ -32,7 +32,7 @@ GitHub's current OIDC guidance is linked from the
32
32
  ## Publish an accepted tag
33
33
 
34
34
  1. Open **Actions → Publish package to PyPI → Run workflow**.
35
- 2. Enter an existing tag such as `v2.1.0`.
35
+ 2. Enter an existing tag such as `v2.2.0`.
36
36
  3. Approve the `pypi` environment when protection rules require it.
37
37
  4. After success, install in a clean environment and compare the installed
38
38
  version and wheel hash with the GitHub Release asset.
@@ -2,7 +2,7 @@ ragops_release_gate:
2
2
  stage: test
3
3
  image: python:3.12-slim
4
4
  variables:
5
- RAGOPS_VERSION: "2.1.0"
5
+ RAGOPS_VERSION: "2.3.0"
6
6
  RAGOPS_SCENARIO: "scenarios/japanese_troubleshooting/benchmark-v0.2.json"
7
7
  RAGOPS_BASELINE: "scenarios/japanese_troubleshooting/benchmark-baseline.json"
8
8
  RAGOPS_CANDIDATE: "scenarios/japanese_troubleshooting/benchmark-regressed.json"
@@ -0,0 +1,24 @@
1
+ # Requirements v2.3 — release integrity and discoverability
2
+
3
+ ## User story
4
+
5
+ As a maintainer or adopter, I can identify the installed RAGOps version and
6
+ verify that a locally built wheel installs cleanly before publication, even when
7
+ GitHub Actions is unavailable.
8
+
9
+ ## Acceptance criteria
10
+
11
+ - `ragops --version` prints the package version and exits zero.
12
+ - Local release verification installs the built wheel into a fresh virtualenv.
13
+ - Artifact checksums are verified in dependency-free Python on every supported
14
+ operating system and reject missing, traversing, or tampered targets.
15
+ - Current-state documentation and integration examples reference one stable
16
+ release; historical release records remain unchanged.
17
+ - Ruff, full tests, deterministic PASS/BLOCK fixtures, package build, clean
18
+ install, GitHub Release, and exact PyPI promotion pass locally.
19
+
20
+ ## Compatibility and non-goals
21
+
22
+ The CLI flag and release checks are additive. No schema, metric, gate meaning,
23
+ API contract, or open-core boundary changes. Hosted infrastructure, real-user
24
+ adoption evidence, and security testing are outside this release.
@@ -59,7 +59,7 @@ PR comment integration and notifications remain hosted/integration work.
59
59
  - GitHub discovery metadata, Discussions, and real starter issues.
60
60
  - GitLab CI release-gate recipe and reviewed least-privilege PR-comment design.
61
61
 
62
- ## 1.8 — review visibility and measured adoption (complete on main, unreleased)
62
+ ## 1.8 — review visibility and measured adoption (released)
63
63
 
64
64
  - Isolated, write-enabled PR comment publisher with bounded artifact parsing,
65
65
  exact metadata verification, pinned actions, and idempotent updates.
@@ -84,6 +84,17 @@ PR comment integration and notifications remain hosted/integration work.
84
84
  dependencies in the core.
85
85
  - Copyable downstream PR-comment publisher recipe with explicit trust boundary.
86
86
 
87
+ ## 2.2 — quota-independent release fallback (released)
88
+
89
+ - Local quality gates, build-once packages, SBOM, checksums, and evidence.
90
+ - Direct GitHub CLI publication and fail-closed project-token PyPI promotion.
91
+
92
+ ## 2.3 — release integrity and discoverability
93
+
94
+ - Installed CLI version diagnostics.
95
+ - Clean-wheel smoke testing before tagging.
96
+ - Dependency-free cross-platform checksum verification.
97
+
87
98
  ## 3.0 — hosted control plane (local alpha boundary implemented)
88
99
 
89
100
  - Workspace isolation, SSO/RBAC, audit retention, managed ingestion, and
@@ -24,6 +24,13 @@ backed by a versioned scenario and persisted report.
24
24
  - Core test and lint pass rate remains 100% on supported Python versions.
25
25
  - Median local deterministic run remains below one second for 1,000 cases.
26
26
 
27
+ ## Release integrity
28
+
29
+ - Published GitHub and PyPI wheel/source hashes match exactly: target 100%.
30
+ - Every stable release passes clean-wheel installation before tagging: target 100%.
31
+ - Every local release records version, commit, checksums, SBOM, and validation result.
32
+ - Release evidence must distinguish OIDC provenance from local-token publication.
33
+
27
34
  ## Commercial signals
28
35
 
29
36
  - Teams requesting shared datasets, SSO/RBAC, audit retention, or hosted runs.
@@ -32,4 +39,3 @@ backed by a versioned scenario and persisted report.
32
39
 
33
40
  These are proposed targets. Public claims must use measured repository or
34
41
  product telemetry, never illustrative values presented as real adoption.
35
-
@@ -24,6 +24,8 @@ public presentation assets.
24
24
  | v1.8 review visibility and measured adoption | Released | `docs/project/v1.8-acceptance.md` |
25
25
  | v2.0 trustworthy extensible release gates | Released | `docs/project/v2.0-acceptance.md` |
26
26
  | v2.1 portable external evaluator evidence | Released | `docs/project/v2.1-acceptance.md` |
27
+ | v2.2 quota-independent release | Released | `docs/project/v2.2-acceptance.md` |
28
+ | v2.3 release integrity | Ready | `docs/project/v2.3-acceptance.md` |
27
29
 
28
30
  ## FDE competency coverage
29
31
 
@@ -42,7 +44,8 @@ public presentation assets.
42
44
  ## Verification baseline
43
45
 
44
46
  - Python 3.11+ dependency-free core.
45
- - 126 automated tests on Python 3.11, 3.12, and 3.13 at the latest acceptance run.
47
+ - 140+ automated tests; the last CI matrix covered Python 3.11, 3.12, and 3.13,
48
+ while v2.2+ release gates run locally during the Actions quota pause.
46
49
  - GitHub/PyPI distributions are byte-identical; GitHub Release includes a
47
50
  reproducible CycloneDX SBOM, SHA-256 manifest, and provenance attestation.
48
51
  - Ruff and diff checks pass.
@@ -63,6 +66,6 @@ therefore launch activities rather than missing repository implementation:
63
66
 
64
67
  ## Final recommendation
65
68
 
66
- Use release 2.1.0 for FDE interviews, OSS feedback, and customer discovery.
69
+ Use the latest stable release for FDE interviews, OSS feedback, and customer discovery.
67
70
  Proceed to a real offline design-partner pilot; do not market the control-plane
68
71
  alpha as production SaaS or claim measured ROI until external evidence exists.
@@ -2,8 +2,9 @@
2
2
 
3
3
  ## Decision
4
4
 
5
- **READY FOR LOCAL RELEASE.** Owner authorization was given to implement and
6
- release without GitHub Actions while the monthly quota is exhausted.
5
+ **RELEASED as 2.2.0 without GitHub Actions.** Owner authorization was given to
6
+ implement and release while the monthly quota was exhausted. GitHub and PyPI
7
+ publication are public and independently verified.
7
8
 
8
9
  ## Contract impact
9
10
 
@@ -17,10 +18,10 @@ gate meaning, existing CLI/API contracts, or the open-core boundary.
17
18
  | Requirement and ADR | Pass | Requirements v2.2 and ADR 0019 |
18
19
  | Fail-closed publication | Pass | Explicit `--yes`; PyPI also requires `PYPI_API_TOKEN` |
19
20
  | Exact artifact promotion | Pass | PyPI phase downloads and verifies GitHub Release checksums; no rebuild |
20
- | Core quality | Pass | Ruff clean; 133 passed, 1 skipped locally |
21
+ | Core quality | Pass | Release virtualenv: Ruff clean; 141 tests passed locally |
21
22
  | GitHub Actions quota | Pass | Triggering workflows disabled manually before repository publication |
22
- | GitHub Release | Pending | Run local verify on the release commit, then publish with `gh` |
23
- | PyPI | Pending | Requires a project-scoped API token; GitHub OIDC is unavailable locally |
23
+ | GitHub Release | Pass | Public v2.2.0 contains wheel, source, SBOM, checksums, and local evidence |
24
+ | PyPI | Pass | Public 2.2.0 wheel/source hashes match GitHub byte-for-byte; clean install reports 2.2.0 |
24
25
 
25
26
  ## Limitations
26
27
 
@@ -0,0 +1,30 @@
1
+ # v2.3 release integrity acceptance
2
+
3
+ ## Decision
4
+
5
+ **READY FOR LOCAL RELEASE.** Owner authorized staged implementation and stable
6
+ publication without GitHub Actions while quota is exhausted.
7
+
8
+ ## Contract impact
9
+
10
+ Additive CLI discoverability and release verification only. Public schemas,
11
+ metrics, gate semantics, API behavior, and open-core boundaries are unchanged.
12
+
13
+ ## Acceptance evidence
14
+
15
+ | Gate | Result | Evidence |
16
+ | --- | --- | --- |
17
+ | Requirement and ADR | Pass | Requirements v2.3 and ADR 0020 |
18
+ | CLI version | Pending | Installed CLI must print `ragops 2.3.0` |
19
+ | Cross-platform checksums | Pending | Unit and tamper tests plus release-download verification |
20
+ | Clean wheel | Pending | Fresh virtualenv install in local release lane |
21
+ | Product flow | Pass | Current workbench input/decision/history flow captured in `docs/design-audit/v2.3/` |
22
+ | KPI evidence | Pass | Release integrity KPIs added without inventing adoption data |
23
+ | Core quality | Pending | Ruff and full offline suite |
24
+ | Public artifacts | Pending | GitHub and PyPI hashes must match |
25
+
26
+ ## Limitations
27
+
28
+ - Supported-Python matrix CI is paused until Actions capacity returns.
29
+ - Hosted infrastructure and design-partner outcomes remain external work.
30
+ - Security testing is deferred by owner instruction.
@@ -0,0 +1,22 @@
1
+ # RAGOps v2.3.0 — release integrity and discoverability
2
+
3
+ RAGOps v2.3.0 makes quota-independent releases easier to verify and diagnose.
4
+
5
+ ## Highlights
6
+
7
+ - Inspect the installed package with `ragops --version`.
8
+ - Install the newly built wheel in a clean virtualenv before any tag or release.
9
+ - Verify GitHub Release checksums with dependency-free, cross-platform Python.
10
+ - Keep current documentation and downstream integration examples aligned with
11
+ the stable public version.
12
+
13
+ ## Compatibility
14
+
15
+ This additive minor release changes no schema, metric, release threshold,
16
+ existing command, API contract, or open-core boundary.
17
+
18
+ ## Known limits
19
+
20
+ The local lane does not carry GitHub OIDC build provenance. Hosted 3.0 and real
21
+ design-partner evidence still require external infrastructure and users.
22
+ Security testing remains deferred by owner instruction.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ragops"
7
- version = "2.2.0"
7
+ version = "2.3.0"
8
8
  description = "Evaluation and red-team release gates for RAG and agent systems"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -14,6 +14,7 @@ import os
14
14
  import shutil
15
15
  import subprocess
16
16
  import sys
17
+ import tempfile
17
18
  import tomllib
18
19
  from datetime import UTC, datetime
19
20
  from pathlib import Path
@@ -59,6 +60,39 @@ def checksums(paths: list[Path]) -> Path:
59
60
  return manifest
60
61
 
61
62
 
63
+ def verify_checksums(directory: Path) -> None:
64
+ manifest = directory / "SHA256SUMS"
65
+ if not manifest.is_file():
66
+ raise SystemExit("release is missing SHA256SUMS")
67
+ lines = manifest.read_text(encoding="utf-8").splitlines()
68
+ if not lines:
69
+ raise SystemExit("SHA256SUMS is empty")
70
+ for line in lines:
71
+ try:
72
+ digest, filename = line.split(" ", 1)
73
+ except ValueError as exc:
74
+ raise SystemExit("invalid SHA256SUMS line") from exc
75
+ path = directory / filename
76
+ if Path(filename).name != filename or not path.is_file():
77
+ raise SystemExit(f"invalid checksum target: {filename}")
78
+ actual = hashlib.sha256(path.read_bytes()).hexdigest()
79
+ if len(digest) != 64 or actual != digest:
80
+ raise SystemExit(f"checksum mismatch: {filename}")
81
+
82
+
83
+ def verify_clean_install(wheel: Path, expected_version: str) -> None:
84
+ with tempfile.TemporaryDirectory(prefix="ragops-release-") as temp:
85
+ venv = Path(temp) / "venv"
86
+ run(sys.executable, "-m", "venv", str(venv))
87
+ python = venv / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
88
+ run(str(python), "-m", "pip", "install", "--no-deps", str(wheel))
89
+ run(
90
+ str(python),
91
+ "-c",
92
+ f"import ragops; assert ragops.__version__ == {expected_version!r}",
93
+ )
94
+
95
+
62
96
  def verify(tag: str) -> None:
63
97
  assert_tag(tag)
64
98
  run("ruff", "check", ".")
@@ -77,6 +111,8 @@ def verify(tag: str) -> None:
77
111
  shutil.rmtree(DIST, ignore_errors=True)
78
112
  run(sys.executable, "-m", "build")
79
113
  built = artifacts()
114
+ wheel = next(path for path in built if path.suffix == ".whl")
115
+ verify_clean_install(wheel, version())
80
116
  sbom = DIST / f"ragops-{version()}.cdx.json"
81
117
  if shutil.which("cyclonedx-py"):
82
118
  run("cyclonedx-py", "environment", sys.executable, "--output-reproducible",
@@ -123,7 +159,7 @@ def pypi(tag: str, yes: bool) -> None:
123
159
  shutil.rmtree(release_dir, ignore_errors=True)
124
160
  release_dir.mkdir(parents=True)
125
161
  run("gh", "release", "download", tag, "--dir", str(release_dir))
126
- run("shasum", "-a", "256", "-c", "SHA256SUMS", cwd=release_dir)
162
+ verify_checksums(release_dir)
127
163
  distributions = sorted(release_dir.glob("ragops-*.whl")) + sorted(release_dir.glob("ragops-*.tar.gz"))
128
164
  if len(distributions) != 2:
129
165
  raise SystemExit("GitHub Release must contain exactly one wheel and one source distribution")
@@ -3,7 +3,7 @@
3
3
  from ragops.engine import compare, evaluate
4
4
  from ragops.loader import load_responses, load_scenario, responses_from_data, scenario_from_dict
5
5
 
6
- __version__ = "2.2.0"
6
+ __version__ = "2.3.0"
7
7
 
8
8
  __all__ = [
9
9
  "compare",
@@ -4,6 +4,7 @@ import argparse
4
4
  import json
5
5
  from pathlib import Path
6
6
 
7
+ from ragops import __version__
7
8
  from ragops.adapters.external_metrics import (
8
9
  load_external_metric_evaluator,
9
10
  validate_external_metric_pair,
@@ -36,6 +37,7 @@ from ragops.traces import load_trace_jsonl
36
37
 
37
38
  def build_parser() -> argparse.ArgumentParser:
38
39
  parser = argparse.ArgumentParser(prog="ragops")
40
+ parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
39
41
  commands = parser.add_subparsers(dest="command", required=True)
40
42
  demo_parser = commands.add_parser("demo", help="Generate a credential-free release-gate demo")
41
43
  demo_parser.add_argument("--output", default="ragops-demo")
@@ -5,7 +5,7 @@ from pathlib import Path
5
5
  def test_gitlab_recipe_preserves_evidence_and_exit_code() -> None:
6
6
  recipe = Path("docs/examples/gitlab-ci-ragops.yml").read_text(encoding="utf-8")
7
7
 
8
- assert 'RAGOPS_VERSION: "2.1.0"' in recipe
8
+ assert 'RAGOPS_VERSION: "2.3.0"' in recipe
9
9
  assert 'if: \'$CI_PIPELINE_SOURCE == "merge_request_event"\'' in recipe
10
10
  assert "gate_exit=$?" in recipe
11
11
  assert 'exit "$gate_exit"' in recipe
@@ -19,6 +19,31 @@ def test_checksum_manifest_is_deterministic(tmp_path, monkeypatch) -> None:
19
19
  manifest = local_release.checksums([artifact])
20
20
  assert manifest.read_text().endswith(" artifact.whl\n")
21
21
  assert len(manifest.read_text().split()[0]) == 64
22
+ local_release.verify_checksums(tmp_path)
23
+
24
+
25
+ def test_checksum_verification_rejects_tampering(tmp_path, monkeypatch) -> None:
26
+ monkeypatch.setattr(local_release, "DIST", tmp_path)
27
+ artifact = tmp_path / "artifact.whl"
28
+ artifact.write_bytes(b"ragops")
29
+ local_release.checksums([artifact])
30
+ artifact.write_bytes(b"tampered")
31
+ try:
32
+ local_release.verify_checksums(tmp_path)
33
+ except SystemExit as error:
34
+ assert "checksum mismatch" in str(error)
35
+ else:
36
+ raise AssertionError("tampered artifact must be rejected")
37
+
38
+
39
+ def test_checksum_verification_rejects_path_traversal(tmp_path) -> None:
40
+ (tmp_path / "SHA256SUMS").write_text(f"{'0' * 64} ../outside.whl\n")
41
+ try:
42
+ local_release.verify_checksums(tmp_path)
43
+ except SystemExit as error:
44
+ assert "invalid checksum target" in str(error)
45
+ else:
46
+ raise AssertionError("checksum target must stay inside release directory")
22
47
 
23
48
 
24
49
  def test_pypi_requires_explicit_token(monkeypatch) -> None:
@@ -1,8 +1,19 @@
1
1
  from ragops import __version__, responses_from_data, scenario_from_dict
2
+ from ragops.cli import build_parser
2
3
 
3
4
 
4
5
  def test_stable_version() -> None:
5
- assert __version__ == "2.2.0"
6
+ assert __version__ == "2.3.0"
7
+
8
+
9
+ def test_cli_exposes_version(capsys) -> None:
10
+ try:
11
+ build_parser().parse_args(["--version"])
12
+ except SystemExit as error:
13
+ assert error.code == 0
14
+ else:
15
+ raise AssertionError("argparse version action must exit")
16
+ assert capsys.readouterr().out.strip() == f"ragops {__version__}"
6
17
 
7
18
 
8
19
  def test_public_contract_parsers() -> None:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes