ragops 2.1.0__tar.gz → 2.2.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 (265) hide show
  1. {ragops-2.1.0 → ragops-2.2.0}/CHANGELOG.md +8 -0
  2. ragops-2.2.0/NEXT_SESSION.md +195 -0
  3. {ragops-2.1.0 → ragops-2.2.0}/PKG-INFO +1 -1
  4. ragops-2.2.0/docs/architecture/adr/0019-local-release-fallback.md +22 -0
  5. ragops-2.2.0/docs/engineering/local-release.md +32 -0
  6. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/pypi-publishing.md +3 -3
  7. ragops-2.2.0/docs/product/requirements-v2.2.md +24 -0
  8. {ragops-2.1.0 → ragops-2.2.0}/docs/project/program-completion-audit.md +2 -2
  9. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v2.1-acceptance.md +6 -4
  10. ragops-2.2.0/docs/project/v2.2-acceptance.md +29 -0
  11. ragops-2.2.0/docs/releases/v2.2.0.md +27 -0
  12. {ragops-2.1.0 → ragops-2.2.0}/pyproject.toml +1 -1
  13. ragops-2.2.0/scripts/local_release.py +153 -0
  14. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/__init__.py +1 -1
  15. ragops-2.2.0/tests/test_local_release.py +31 -0
  16. {ragops-2.1.0 → ragops-2.2.0}/tests/test_public_api.py +1 -1
  17. {ragops-2.1.0 → ragops-2.2.0}/.dockerignore +0 -0
  18. {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  19. {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/design-partner.yml +0 -0
  21. {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/evaluator.yml +0 -0
  22. {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
  23. {ragops-2.1.0 → ragops-2.2.0}/.github/pull_request_template.md +0 -0
  24. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ci.yml +0 -0
  25. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/nightly.yml +0 -0
  26. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/pages.yml +0 -0
  27. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/publish-pypi.yml +0 -0
  28. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ragops-gate-smoke.yml +0 -0
  29. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ragops-gate.yml +0 -0
  30. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ragops-pr-comment.yml +0 -0
  31. {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/release.yml +0 -0
  32. {ragops-2.1.0 → ragops-2.2.0}/.gitignore +0 -0
  33. {ragops-2.1.0 → ragops-2.2.0}/AGENTS.md +0 -0
  34. {ragops-2.1.0 → ragops-2.2.0}/CODE_OF_CONDUCT.md +0 -0
  35. {ragops-2.1.0 → ragops-2.2.0}/CONTRIBUTING.md +0 -0
  36. {ragops-2.1.0 → ragops-2.2.0}/Dockerfile +0 -0
  37. {ragops-2.1.0 → ragops-2.2.0}/LICENSE +0 -0
  38. {ragops-2.1.0 → ragops-2.2.0}/README.md +0 -0
  39. {ragops-2.1.0 → ragops-2.2.0}/SECURITY.md +0 -0
  40. {ragops-2.1.0 → ragops-2.2.0}/SUPPORT.md +0 -0
  41. {ragops-2.1.0 → ragops-2.2.0}/apps/__init__.py +0 -0
  42. {ragops-2.1.0 → ragops-2.2.0}/apps/api/__init__.py +0 -0
  43. {ragops-2.1.0 → ragops-2.2.0}/apps/api/main.py +0 -0
  44. {ragops-2.1.0 → ragops-2.2.0}/apps/github_pr_comment.py +0 -0
  45. {ragops-2.1.0 → ragops-2.2.0}/apps/web/index.html +0 -0
  46. {ragops-2.1.0 → ragops-2.2.0}/compose.yaml +0 -0
  47. {ragops-2.1.0 → ragops-2.2.0}/design-qa.md +0 -0
  48. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0001-local-first-core.md +0 -0
  49. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0002-baseline-regression-gates.md +0 -0
  50. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0003-reference-app-outside-core.md +0 -0
  51. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0004-open-core-boundary.md +0 -0
  52. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0005-scenario-0.2-metadata-and-citation-precision.md +0 -0
  53. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0006-response-fixture-overlays.md +0 -0
  54. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0007-offline-reference-graphrag-agent.md +0 -0
  55. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0008-local-team-review-workflow.md +0 -0
  56. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0009-adopt-mit-license.md +0 -0
  57. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0010-repair-trace-04-schema-json.md +0 -0
  58. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0011-reusable-pr-gate-is-an-adapter.md +0 -0
  59. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0012-opentelemetry-export-is-an-example-adapter.md +0 -0
  60. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0013-additive-demo-catalog-and-codepoint-budget.md +0 -0
  61. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0014-separate-pr-evaluation-from-comment-publication.md +0 -0
  62. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0015-portable-design-partner-measurement.md +0 -0
  63. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0016-first-class-evaluator-gates.md +0 -0
  64. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0017-api-authentication-and-input-bounds.md +0 -0
  65. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0018-portable-external-metric-envelope.md +0 -0
  66. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/component-diagram.md +0 -0
  67. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/context-diagram.md +0 -0
  68. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/control-plane-alpha.md +0 -0
  69. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/data-model.md +0 -0
  70. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/pr-comment-publishing.md +0 -0
  71. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/system-overview.md +0 -0
  72. {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/threat-model.md +0 -0
  73. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/cv-linkedin-copy.md +0 -0
  74. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/01-current-desktop.jpg +0 -0
  75. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/02-implementation-desktop.jpg +0 -0
  76. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/04-implementation-mobile.jpg +0 -0
  77. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/06-desktop-comparison.jpg +0 -0
  78. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/09-limitations-section.jpg +0 -0
  79. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/selected-open-source-adoption.png +0 -0
  80. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/infographics/evidence-stack.svg +0 -0
  81. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/infographics/release-gate-flow.svg +0 -0
  82. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/portfolio-case-study.md +0 -0
  83. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/portfolio-handoff.md +0 -0
  84. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/presentation-outline.md +0 -0
  85. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-limitations-screen.jpg +0 -0
  86. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-mobile-screen.jpg +0 -0
  87. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-portfolio-desktop.jpg +0 -0
  88. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-portfolio-mobile.jpg +0 -0
  89. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-release-screen.jpg +0 -0
  90. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-showcase-hero.jpg +0 -0
  91. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/social-preview.png +0 -0
  92. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/video-script.md +0 -0
  93. {ragops-2.1.0 → ragops-2.2.0}/docs/demo/walkthrough.md +0 -0
  94. {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/01-start.png +0 -0
  95. {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/02-pass-decision.png +0 -0
  96. {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/03-invalid-json-stale-decision.png +0 -0
  97. {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/04-fixed-pass-decision.png +0 -0
  98. {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/05-fixed-invalid-json.png +0 -0
  99. {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/workbench-audit.md +0 -0
  100. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/export-your-first-trace.md +0 -0
  101. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/github-pr-gate.md +0 -0
  102. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/gitlab-ci-gate.md +0 -0
  103. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/handbook.md +0 -0
  104. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/observability.md +0 -0
  105. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/provider-adapters.md +0 -0
  106. {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/testing-strategy.md +0 -0
  107. {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/answer-length-budget.md +0 -0
  108. {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/benchmark-report-v0.2.md +0 -0
  109. {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/evaluator-gates.md +0 -0
  110. {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/red-team-plan.md +0 -0
  111. {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/scenario-taxonomy.md +0 -0
  112. {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/strategy.md +0 -0
  113. {ragops-2.1.0 → ragops-2.2.0}/docs/examples/github-pr-comment.yml +0 -0
  114. {ragops-2.1.0 → ragops-2.2.0}/docs/examples/gitlab-ci-ragops.yml +0 -0
  115. {ragops-2.1.0 → ragops-2.2.0}/docs/getting-started.md +0 -0
  116. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/design-partner-outreach.md +0 -0
  117. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/design-partner-pilot-runbook.md +0 -0
  118. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/github-launch-checklist.md +0 -0
  119. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-fixtures/synthetic-economics.json +0 -0
  120. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-fixtures/synthetic-manifest.json +0 -0
  121. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-fixtures/synthetic-observations.jsonl +0 -0
  122. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-measurement-plan.md +0 -0
  123. {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/synthetic-pilot-report.md +0 -0
  124. {ragops-2.1.0 → ragops-2.2.0}/docs/product/commercialization.md +0 -0
  125. {ragops-2.1.0 → ragops-2.2.0}/docs/product/competitive-analysis.md +0 -0
  126. {ragops-2.1.0 → ragops-2.2.0}/docs/product/jobs-to-be-done.md +0 -0
  127. {ragops-2.1.0 → ragops-2.2.0}/docs/product/oss-launch-plan.md +0 -0
  128. {ragops-2.1.0 → ragops-2.2.0}/docs/product/personas.md +0 -0
  129. {ragops-2.1.0 → ragops-2.2.0}/docs/product/product_thesis.md +0 -0
  130. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v0.1.md +0 -0
  131. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v0.2.md +0 -0
  132. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.5.md +0 -0
  133. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.6.md +0 -0
  134. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.7.md +0 -0
  135. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.8.md +0 -0
  136. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v2.0.md +0 -0
  137. {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v2.1.md +0 -0
  138. {ragops-2.1.0 → ragops-2.2.0}/docs/product/roadmap.md +0 -0
  139. {ragops-2.1.0 → ragops-2.2.0}/docs/product/success-metrics.md +0 -0
  140. {ragops-2.1.0 → ragops-2.2.0}/docs/project/backlog.md +0 -0
  141. {ragops-2.1.0 → ragops-2.2.0}/docs/project/charter.md +0 -0
  142. {ragops-2.1.0 → ragops-2.2.0}/docs/project/decision-log.md +0 -0
  143. {ragops-2.1.0 → ragops-2.2.0}/docs/project/m1-acceptance.md +0 -0
  144. {ragops-2.1.0 → ragops-2.2.0}/docs/project/m2-acceptance.md +0 -0
  145. {ragops-2.1.0 → ragops-2.2.0}/docs/project/m3-acceptance.md +0 -0
  146. {ragops-2.1.0 → ragops-2.2.0}/docs/project/m4-acceptance.md +0 -0
  147. {ragops-2.1.0 → ragops-2.2.0}/docs/project/m5-acceptance.md +0 -0
  148. {ragops-2.1.0 → ragops-2.2.0}/docs/project/milestones.md +0 -0
  149. {ragops-2.1.0 → ragops-2.2.0}/docs/project/release-plan.md +0 -0
  150. {ragops-2.1.0 → ragops-2.2.0}/docs/project/risk-register.md +0 -0
  151. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1-acceptance.md +0 -0
  152. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.5-acceptance.md +0 -0
  153. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.6-acceptance.md +0 -0
  154. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.7-acceptance.md +0 -0
  155. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.8-acceptance.md +0 -0
  156. {ragops-2.1.0 → ragops-2.2.0}/docs/project/v2.0-acceptance.md +0 -0
  157. {ragops-2.1.0 → ragops-2.2.0}/docs/project/work-breakdown.md +0 -0
  158. {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.5.0.md +0 -0
  159. {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.6.0.md +0 -0
  160. {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.7.0.md +0 -0
  161. {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.8.0.md +0 -0
  162. {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v2.0.0.md +0 -0
  163. {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v2.1.0.md +0 -0
  164. {ragops-2.1.0 → ragops-2.2.0}/examples/__init__.py +0 -0
  165. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/README.md +0 -0
  166. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/__init__.py +0 -0
  167. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/agent.py +0 -0
  168. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/architecture.md +0 -0
  169. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/cli.py +0 -0
  170. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/data/documents.json +0 -0
  171. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/data/graph.json +0 -0
  172. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/discovery.md +0 -0
  173. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/executive-report.md +0 -0
  174. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/results/comparison.md +0 -0
  175. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/results/graph-traces.jsonl +0 -0
  176. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/results/lexical-traces.jsonl +0 -0
  177. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/rollout-plan.md +0 -0
  178. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/scenario.json +0 -0
  179. {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/suite.json +0 -0
  180. {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/README.md +0 -0
  181. {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/__init__.py +0 -0
  182. {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/adapter.py +0 -0
  183. {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/spans.jsonl +0 -0
  184. {ragops-2.1.0 → ragops-2.2.0}/ragops.toml +0 -0
  185. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/attack-pack.json +0 -0
  186. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-adversarial.json +0 -0
  187. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-baseline.json +0 -0
  188. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-regressed.json +0 -0
  189. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-v0.2.json +0 -0
  190. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/evaluation-policy.toml +0 -0
  191. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/external-metric-policy.toml +0 -0
  192. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/external-metrics-baseline.json +0 -0
  193. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/external-metrics-candidate.json +0 -0
  194. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/regressed_responses.json +0 -0
  195. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/sample_responses.json +0 -0
  196. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/sample_traces.jsonl +0 -0
  197. {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/scenario.json +0 -0
  198. {ragops-2.1.0 → ragops-2.2.0}/schemas/attack-pack-0.1.schema.json +0 -0
  199. {ragops-2.1.0 → ragops-2.2.0}/schemas/external-metrics-0.1.schema.json +0 -0
  200. {ragops-2.1.0 → ragops-2.2.0}/schemas/pilot-economics-0.1.schema.json +0 -0
  201. {ragops-2.1.0 → ragops-2.2.0}/schemas/pilot-manifest-0.1.schema.json +0 -0
  202. {ragops-2.1.0 → ragops-2.2.0}/schemas/pilot-observation-0.1.schema.json +0 -0
  203. {ragops-2.1.0 → ragops-2.2.0}/schemas/report-0.2.schema.json +0 -0
  204. {ragops-2.1.0 → ragops-2.2.0}/schemas/response-fixture-0.2.schema.json +0 -0
  205. {ragops-2.1.0 → ragops-2.2.0}/schemas/responses-0.1.schema.json +0 -0
  206. {ragops-2.1.0 → ragops-2.2.0}/schemas/scenario-0.1.schema.json +0 -0
  207. {ragops-2.1.0 → ragops-2.2.0}/schemas/scenario-0.2.schema.json +0 -0
  208. {ragops-2.1.0 → ragops-2.2.0}/schemas/trace-0.3.schema.json +0 -0
  209. {ragops-2.1.0 → ragops-2.2.0}/schemas/trace-0.4.schema.json +0 -0
  210. {ragops-2.1.0 → ragops-2.2.0}/site/apple-touch-icon.png +0 -0
  211. {ragops-2.1.0 → ragops-2.2.0}/site/favicon.png +0 -0
  212. {ragops-2.1.0 → ragops-2.2.0}/site/index.html +0 -0
  213. {ragops-2.1.0 → ragops-2.2.0}/site/styles.css +0 -0
  214. {ragops-2.1.0 → ragops-2.2.0}/skills/ragops-feature/SKILL.md +0 -0
  215. {ragops-2.1.0 → ragops-2.2.0}/skills/ragops-presentation/SKILL.md +0 -0
  216. {ragops-2.1.0 → ragops-2.2.0}/skills/ragops-release/SKILL.md +0 -0
  217. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/adapters/__init__.py +0 -0
  218. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/adapters/external_metrics.py +0 -0
  219. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/adapters/http.py +0 -0
  220. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/benchmarks.py +0 -0
  221. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/cli.py +0 -0
  222. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/config.py +0 -0
  223. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/control_plane.py +0 -0
  224. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/demo.py +0 -0
  225. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/engine.py +0 -0
  226. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/evaluators.py +0 -0
  227. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/loader.py +0 -0
  228. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/models.py +0 -0
  229. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/pilot.py +0 -0
  230. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/plugins.py +0 -0
  231. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/providers/__init__.py +0 -0
  232. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/providers/openai_responses.py +0 -0
  233. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/reporters.py +0 -0
  234. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/store.py +0 -0
  235. {ragops-2.1.0 → ragops-2.2.0}/src/ragops/traces.py +0 -0
  236. {ragops-2.1.0 → ragops-2.2.0}/tests/test_adoption_recipes.py +0 -0
  237. {ragops-2.1.0 → ragops-2.2.0}/tests/test_answer_length_cli.py +0 -0
  238. {ragops-2.1.0 → ragops-2.2.0}/tests/test_api_contract.py +0 -0
  239. {ragops-2.1.0 → ragops-2.2.0}/tests/test_benchmarks.py +0 -0
  240. {ragops-2.1.0 → ragops-2.2.0}/tests/test_comparison.py +0 -0
  241. {ragops-2.1.0 → ragops-2.2.0}/tests/test_config.py +0 -0
  242. {ragops-2.1.0 → ragops-2.2.0}/tests/test_control_plane.py +0 -0
  243. {ragops-2.1.0 → ragops-2.2.0}/tests/test_demo.py +0 -0
  244. {ragops-2.1.0 → ragops-2.2.0}/tests/test_engine.py +0 -0
  245. {ragops-2.1.0 → ragops-2.2.0}/tests/test_evaluator_depth.py +0 -0
  246. {ragops-2.1.0 → ragops-2.2.0}/tests/test_external_metrics.py +0 -0
  247. {ragops-2.1.0 → ragops-2.2.0}/tests/test_github_workflows.py +0 -0
  248. {ragops-2.1.0 → ragops-2.2.0}/tests/test_http_adapter.py +0 -0
  249. {ragops-2.1.0 → ragops-2.2.0}/tests/test_loader.py +0 -0
  250. {ragops-2.1.0 → ragops-2.2.0}/tests/test_openai_provider.py +0 -0
  251. {ragops-2.1.0 → ragops-2.2.0}/tests/test_opentelemetry_adapter.py +0 -0
  252. {ragops-2.1.0 → ragops-2.2.0}/tests/test_pilot.py +0 -0
  253. {ragops-2.1.0 → ragops-2.2.0}/tests/test_plugins_and_traces.py +0 -0
  254. {ragops-2.1.0 → ragops-2.2.0}/tests/test_pr_comment_publisher.py +0 -0
  255. {ragops-2.1.0 → ragops-2.2.0}/tests/test_readme_visuals.py +0 -0
  256. {ragops-2.1.0 → ragops-2.2.0}/tests/test_reference_agent.py +0 -0
  257. {ragops-2.1.0 → ragops-2.2.0}/tests/test_reference_benchmark.py +0 -0
  258. {ragops-2.1.0 → ragops-2.2.0}/tests/test_release_version.py +0 -0
  259. {ragops-2.1.0 → ragops-2.2.0}/tests/test_response_fixtures.py +0 -0
  260. {ragops-2.1.0 → ragops-2.2.0}/tests/test_scenario_v02_and_attacks.py +0 -0
  261. {ragops-2.1.0 → ragops-2.2.0}/tests/test_schema_files.py +0 -0
  262. {ragops-2.1.0 → ragops-2.2.0}/tests/test_showcase_site.py +0 -0
  263. {ragops-2.1.0 → ragops-2.2.0}/tests/test_store_and_html.py +0 -0
  264. {ragops-2.1.0 → ragops-2.2.0}/tests/test_team_workflow.py +0 -0
  265. {ragops-2.1.0 → ragops-2.2.0}/tests/test_workbench.py +0 -0
@@ -4,6 +4,14 @@ All notable changes follow Keep a Changelog. This project uses Semantic Versioni
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.2.0] - 2026-07-13
8
+
9
+ ### Added
10
+
11
+ - Quota-independent local release fallback with full offline validation,
12
+ build-once artifacts, reproducible SBOM, checksums, GitHub CLI publication,
13
+ and fail-closed optional PyPI token promotion.
14
+
7
15
  ## [2.1.0] - 2026-07-13
8
16
 
9
17
  ### Added
@@ -0,0 +1,195 @@
1
+ # RAGOps — handoff for 2026-07-14
2
+
3
+ > Superseded on 2026-07-13 by the staged completion run. RAGOps v1.8.0 and
4
+ > v2.0.0 and v2.1.0 were released and verified on GitHub and PyPI. The live BLOCK
5
+ > publisher path was proven through PR #7, including an idempotent update of the
6
+ > same comment. v2.0.0 adds first-class evaluator gates, unified compare
7
+ > semantics, strict numeric validation, fail-closed API authentication and
8
+ > bounds, synthetic benchmark positioning, Product Design remediation,
9
+ > Python 3.13 CI, build-once promotion, CycloneDX SBOM, checksums, provenance,
10
+ > and complete package metadata. v2.1.0 adds portable Ragas/DeepEval/Langfuse/
11
+ > custom metric evidence plus a downstream publisher recipe. Canonical evidence
12
+ > is in `docs/project/v2.1-acceptance.md`.
13
+ >
14
+ > Remaining items below that require real design partners, account-owner
15
+ > settings, credential rotation, hosted infrastructure, or an independent
16
+ > security assessment remain external owner work. They are not incomplete core
17
+ > implementation. Security testing stays deferred by explicit owner request.
18
+
19
+ This is a local-only working note. Do not treat unchecked items as shipped or
20
+ as customer evidence.
21
+
22
+ ## Current verified state
23
+
24
+ - Branch: `main`
25
+ - Latest pushed commit: `deeaf7e` (`docs: record live publisher and partner outreach`)
26
+ - Latest public release: `v1.7.0` on GitHub and PyPI
27
+ - v1.8 scope: complete on `main`, not versioned or released
28
+ - Local quality gate: Ruff clean, 99 tests passing, 10 JSON schemas parsing
29
+ - PR publisher live proof: [PR #4](https://github.com/thangldw/ragops/pull/4)
30
+ created one PASS comment and updated the same comment for a second head SHA;
31
+ the PR was closed without merge and the temporary branch was deleted.
32
+ - Design-partner recruitment: [Discussion #5](https://github.com/thangldw/ragops/discussions/5)
33
+ is public. No reviewed real-partner observations or ROI evidence exist yet.
34
+ - Acceptance record: `docs/project/v1.8-acceptance.md`
35
+
36
+ ## P0 — do before a v1.8 release
37
+
38
+ ### 1. Verify the live BLOCK path
39
+
40
+ - [ ] Create a temporary PR that changes the reusable smoke candidate from the
41
+ passing baseline to `benchmark-regressed.json`.
42
+ - [ ] Confirm the release-gate workflow fails with exit `2`.
43
+ - [ ] Confirm the publisher still creates a `BLOCK` comment containing the
44
+ canonical workflow link and correct head SHA.
45
+ - [ ] Push a second commit and confirm the same bot comment is updated rather
46
+ than duplicated.
47
+ - [ ] Close without merge and delete the temporary branch.
48
+ - [ ] Record the PR/run/comment links in `docs/project/v1.8-acceptance.md`.
49
+
50
+ Why: PASS creation/update is proven live; BLOCK publication is covered by unit
51
+ tests but has not yet been exercised end to end on GitHub.
52
+
53
+ ### 2. Decide whether to release v1.8.0
54
+
55
+ - [ ] Owner explicitly selects or rejects the v1.8.0 release boundary.
56
+ - [ ] If GO, use `skills/ragops-release/SKILL.md`.
57
+ - [ ] Bump `pyproject.toml`, `src/ragops/__init__.py`, workflow examples, tests,
58
+ README install command, and issue template from 1.7.0 to 1.8.0.
59
+ - [ ] Move Unreleased changelog entries into `1.8.0` and write
60
+ `docs/releases/v1.8.0.md`.
61
+ - [ ] Run Ruff, full tests on available Python versions, PASS/BLOCK fixtures,
62
+ pilot CLI, API health/evaluate, all schemas, build, wheel/sdist clean install,
63
+ and version-consistency checks.
64
+ - [ ] Tag and publish GitHub Release only after owner GO.
65
+ - [ ] Trigger PyPI Trusted Publishing for `v1.8.0`, then verify public wheel,
66
+ source distribution, clean install, and pilot command.
67
+ - [ ] Update v1.8 acceptance and launch checklist with public artifact evidence.
68
+
69
+ Important: the package metadata on `main` still says `1.7.0`; do not publish a
70
+ build from `main` until the release version is intentionally bumped.
71
+
72
+ ## P0 — real design-partner work
73
+
74
+ ### 3. Qualify the first design partner
75
+
76
+ - [ ] Review replies to Discussion #5; do not infer interest from views or stars.
77
+ - [ ] Select a team with an existing RAG/agent pilot, recurring regression pain,
78
+ a technical owner, and a workflow/business owner.
79
+ - [ ] Hold the 60-minute discovery using
80
+ `docs/gtm/design-partner-outreach.md`.
81
+ - [ ] Agree on one workflow, eligible cohort, baseline/pilot periods, exclusions,
82
+ primary targets, critical stop conditions, and decision owner.
83
+ - [ ] Obtain explicit consent for pseudonymous workflow measurement.
84
+ - [ ] Start with synthetic/redacted traces. Do not collect raw customer
85
+ documents, prompts, names, email addresses, credentials, or secrets.
86
+
87
+ ### 4. Freeze and run the pilot contract
88
+
89
+ - [ ] Copy the synthetic manifest/observations/economics fixtures into a private,
90
+ partner-reviewed workspace; do not commit partner data to the public repo.
91
+ - [ ] Replace synthetic identifiers with pseudonymous IDs.
92
+ - [ ] Collect at least two weeks or 50 eligible baseline tasks when feasible.
93
+ - [ ] Freeze targets before pilot exposure.
94
+ - [ ] Collect pilot observations using the same task definition and exclusions.
95
+ - [ ] Run `ragops pilot-report` without economics first.
96
+ - [ ] Add economics only after the partner reviews hourly cost and pilot
97
+ investment assumptions.
98
+ - [ ] Review SCALE/HOLD/REDESIGN jointly and document owner sign-off.
99
+ - [ ] Publish no adoption or ROI percentage until cohort, period, denominator,
100
+ exclusions, assumptions, consent, and partner approval are documented.
101
+
102
+ Runbook: `docs/gtm/design-partner-pilot-runbook.md`
103
+
104
+ ## P1 — repository and adoption cleanup
105
+
106
+ ### 5. Documentation consistency
107
+
108
+ - [ ] Update `docs/demo/cv-linkedin-copy.md`, which still says 50 automated
109
+ tests; use 99 only if the statement is meant to describe current `main`.
110
+ - [ ] Review historical v1.7 wording that says PR comments are design-only.
111
+ Preserve release history, but link readers to the v1.8 implementation where
112
+ current-state wording could be ambiguous.
113
+ - [ ] Update `docs/project/program-completion-audit.md` after v1.8 is released or
114
+ a real pilot produces evidence.
115
+ - [ ] Recheck README, Pages, portfolio, screenshots, and social preview after
116
+ the next version number/test count changes.
117
+
118
+ ### 6. GitHub owner settings
119
+
120
+ - [ ] Upload `docs/demo/social-preview.png` as the repository social preview if
121
+ it is still not configured.
122
+ - [ ] Configure branch protection and required checks for `main` under the
123
+ owner's collaboration policy.
124
+ - [ ] Decide whether the PR comment publisher should be required, optional, or
125
+ limited to selected paths.
126
+ - [ ] Confirm workflow retention is long enough for audit evidence and short
127
+ enough for the intended data-retention policy.
128
+
129
+ ### 7. Publisher adopter experience
130
+
131
+ - [ ] Add a copyable downstream-repository publisher recipe; the current
132
+ workflow is configured for `RAGOps reusable gate smoke` in this repository.
133
+ - [ ] Document the exact workflow-name allowlist change required by adopters.
134
+ - [ ] Exercise a fork PR. Expected behavior is safe publication when GitHub
135
+ supplies exactly one PR association, otherwise fail closed without a comment.
136
+ - [ ] Add live or fixture coverage for expired artifacts, more than 100
137
+ artifacts, more than 1,000 comments, and GitHub API rate-limit responses.
138
+ - [ ] Decide whether artifact/comment retention and deletion need an ADR.
139
+
140
+ ## P1 — pilot measurement improvements after first feedback
141
+
142
+ - [ ] Confirm whether repeat usage across two ISO weeks is meaningful for the
143
+ partner's workflow cadence.
144
+ - [ ] Decide whether incomplete tasks belong in success and duration
145
+ denominators; current success/duration metrics use completed tasks.
146
+ - [ ] Add explicit exclusion reasons if a real pilot needs auditable exclusions.
147
+ - [ ] Consider paired-task or comparison-cohort analysis before making causal
148
+ claims. Current before/after reporting is observational.
149
+ - [ ] Add uncertainty intervals only when sample size and study design justify
150
+ them; do not create statistical decoration for a tiny pilot.
151
+ - [ ] Validate willingness-to-pay separately from estimated labor savings.
152
+
153
+ ## P2 — not immediate source-code work
154
+
155
+ - [ ] Hosted 2.0 requires cloud, SSO/RBAC, encryption, tenant isolation,
156
+ billing, support, incident response, legal, and operations decisions.
157
+ - [ ] Independent security review is required before processing customer-
158
+ sensitive traces. The previously requested Codex Security scan was explicitly
159
+ skipped and should remain deferred unless the owner reauthorizes it.
160
+ - [ ] Provider-backed judges, plugin sandboxing, signed baselines, and production
161
+ data controls remain future architecture work, not v1.8 release blockers.
162
+
163
+ ## Account hygiene
164
+
165
+ - [ ] Rotate the PyPI password because it was shared in conversation history.
166
+ - [ ] Regenerate PyPI recovery codes because they were also exposed in the
167
+ working context; store the replacement set only in a password manager.
168
+ - [ ] Confirm 2FA and the `thangldw/ragops` Trusted Publisher still work after
169
+ rotation. Do not add a long-lived PyPI token to GitHub secrets.
170
+
171
+ ## Fast start commands
172
+
173
+ ```bash
174
+ cd /Users/thang/Documents/ragops
175
+ git status --short
176
+ git pull --ff-only
177
+ ruff check .
178
+ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest -q
179
+
180
+ PYTHONPATH=src python -m ragops.cli pilot-report \
181
+ --manifest docs/gtm/pilot-fixtures/synthetic-manifest.json \
182
+ --observations docs/gtm/pilot-fixtures/synthetic-observations.jsonl \
183
+ --economics docs/gtm/pilot-fixtures/synthetic-economics.json \
184
+ --output /tmp/ragops-pilot-report.md
185
+
186
+ diff -u docs/gtm/synthetic-pilot-report.md /tmp/ragops-pilot-report.md
187
+ ```
188
+
189
+ ## Recommended order tomorrow
190
+
191
+ 1. Live BLOCK PR publisher test.
192
+ 2. Review Discussion #5 and qualify any real respondent.
193
+ 3. Decide v1.8.0 release GO/HOLD.
194
+ 4. If GO, run the full release workflow.
195
+ 5. Finish documentation/settings cleanup while waiting for partner baseline data.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragops
3
- Version: 2.1.0
3
+ Version: 2.2.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
@@ -0,0 +1,22 @@
1
+ # ADR 0019: Local release fallback
2
+
3
+ Status: Accepted for owner review
4
+
5
+ ## Decision
6
+
7
+ Provide `scripts/local_release.py` with three explicit phases: `verify`,
8
+ `publish-github`, and `publish-pypi`. Verification produces immutable package
9
+ artifacts, an SBOM, checksums, and local evidence. GitHub publication requires
10
+ `--yes`; PyPI additionally requires a project-scoped token supplied only via an
11
+ environment variable and promotes the artifacts downloaded back from GitHub.
12
+
13
+ Workflows may be disabled through the GitHub UI or `gh workflow disable` while
14
+ quota is exhausted. They remain versioned so the owner can restore the preferred
15
+ OIDC/provenance path later.
16
+
17
+ ## Consequences
18
+
19
+ The fallback avoids Actions minutes and keeps release gates observable. Local
20
+ PyPI uploads do not receive GitHub Trusted Publisher identity or GitHub build
21
+ provenance, so `LOCAL_RELEASE_EVIDENCE.json` records `trusted_publishing: false`.
22
+ The owner must protect and rotate the temporary project token.
@@ -0,0 +1,32 @@
1
+ # Release without GitHub Actions
2
+
3
+ Use this only while GitHub Actions is unavailable. Run from a clean release
4
+ commit with Python 3.11+ and `gh` authenticated.
5
+
6
+ ```bash
7
+ python -m pip install -e '.[dev]' build cyclonedx-bom==7.3.0 twine
8
+ python scripts/local_release.py verify --tag vX.Y.Z
9
+ python scripts/local_release.py publish-github --tag vX.Y.Z --yes
10
+ ```
11
+
12
+ The first command runs all required local gates and writes `dist/` artifacts,
13
+ `SHA256SUMS`, an SBOM, and `LOCAL_RELEASE_EVIDENCE.json`. The second creates and
14
+ pushes the annotated tag, then creates the GitHub Release directly with `gh`.
15
+
16
+ PyPI cannot use the repository's GitHub OIDC Trusted Publisher from a local
17
+ machine. If PyPI publication cannot wait, create a project-scoped token, expose
18
+ it only for this command, and rotate/revoke it afterwards:
19
+
20
+ ```bash
21
+ read -s PYPI_API_TOKEN && export PYPI_API_TOKEN
22
+ python scripts/local_release.py publish-pypi --tag vX.Y.Z --yes
23
+ unset PYPI_API_TOKEN
24
+ ```
25
+
26
+ The PyPI phase downloads and verifies the GitHub Release artifacts before
27
+ uploading them; it never rebuilds. Do not paste tokens into chat, shell history,
28
+ configuration files, or repository secrets.
29
+
30
+ Pause quota-consuming workflows with `gh workflow disable <workflow-file>` and
31
+ restore them later with `gh workflow enable <workflow-file>`. Keep manual notes
32
+ of every disabled workflow.
@@ -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.0.0`
12
+ - Current verified release: `2.1.0`
13
13
  - GitHub environment: `pypi`
14
14
  - Publisher: `thangldw/ragops`, workflow `publish-pypi.yml`
15
- - Verification: 2.0.0 wheel and sdist present; clean install and
15
+ - Verification: 2.1.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.0.0`.
35
+ 2. Enter an existing tag such as `v2.1.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.
@@ -0,0 +1,24 @@
1
+ # RAGOps v2.2 requirement: quota-independent release fallback
2
+
3
+ ## Contract
4
+
5
+ When GitHub Actions is unavailable or out of quota, the owner can run the same
6
+ quality gates locally, build artifacts once, and publish those exact artifacts
7
+ without enabling Actions.
8
+
9
+ Acceptance requires Ruff, the complete offline test suite, PASS and BLOCK
10
+ benchmark checks, package build, reproducible CycloneDX SBOM, SHA-256 manifest,
11
+ and machine-readable local evidence. GitHub publication uses `gh` directly.
12
+ PyPI publication is opt-in and fails closed unless a project-scoped API token is
13
+ provided through `PYPI_API_TOKEN`.
14
+
15
+ ## Compatibility
16
+
17
+ This is an additive operational path. It does not change public schemas, metric
18
+ meaning, gate thresholds, CLI contracts, or the open-core boundary.
19
+
20
+ ## Non-goals
21
+
22
+ - Bypassing PyPI authentication or claiming OIDC provenance for a local build.
23
+ - Replacing the normal Trusted Publishing path after Actions capacity returns.
24
+ - Running security tests in this phase.
@@ -23,7 +23,7 @@ public presentation assets.
23
23
  | v1.7 broader adoption proof | Released | `docs/project/v1.7-acceptance.md` |
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
- | v2.1 portable external evaluator evidence | Release candidate | `docs/project/v2.1-acceptance.md` |
26
+ | v2.1 portable external evaluator evidence | Released | `docs/project/v2.1-acceptance.md` |
27
27
 
28
28
  ## FDE competency coverage
29
29
 
@@ -63,6 +63,6 @@ therefore launch activities rather than missing repository implementation:
63
63
 
64
64
  ## Final recommendation
65
65
 
66
- Use release 2.0.0 for FDE interviews, OSS feedback, and customer discovery.
66
+ Use release 2.1.0 for FDE interviews, OSS feedback, and customer discovery.
67
67
  Proceed to a real offline design-partner pilot; do not market the control-plane
68
68
  alpha as production SaaS or claim measured ROI until external evidence exists.
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## Decision
4
4
 
5
- **GO for release 2.1.0. The owner authorized continued staged implementation
6
- and release on 2026-07-13. Public publication remains conditional on release
7
- validation and green GitHub CI.**
5
+ **RELEASED as 2.1.0. The owner authorized continued staged implementation and
6
+ release on 2026-07-13; release validation, GitHub CI, GitHub publication, and
7
+ PyPI promotion all passed.**
8
8
 
9
9
  ## Contract impact
10
10
 
@@ -25,7 +25,9 @@ the producing framework and reviewed policy.
25
25
  | Core boundary | Pass | No Ragas, DeepEval, Langfuse, model SDK, or runtime dependency added |
26
26
  | Downstream publisher | Pass | Actionlint clean; commit-pinned trusted checkout, exact allowlist, least privileges, and no PR-code execution |
27
27
  | Core quality | Pass | Ruff clean and 138 tests pass locally; feature PR passed Python 3.11, 3.12, and 3.13 |
28
- | Release supply chain | Pending | v2.1 tag must prove build-once, SBOM, checksums, provenance, and byte-identical PyPI promotion |
28
+ | Release supply chain | Pass | [Run 29221256309](https://github.com/thangldw/ragops/actions/runs/29221256309) built once and published SBOM, checksums, provenance, wheel, and source |
29
+ | PyPI promotion | Pass | [Run 29221291458](https://github.com/thangldw/ragops/actions/runs/29221291458) verified GitHub Release checksums and published the exact wheel/source |
30
+ | Public artifacts | Pass | [v2.1.0](https://github.com/thangldw/ragops/releases/tag/v2.1.0) and PyPI hashes match byte-for-byte; clean simple-index install reports 2.1.0 and external-metric evaluate exits 0 |
29
31
 
30
32
  ## Limitations
31
33
 
@@ -0,0 +1,29 @@
1
+ # v2.2 quota-independent release acceptance
2
+
3
+ ## Decision
4
+
5
+ **READY FOR LOCAL RELEASE.** Owner authorization was given to implement and
6
+ release without GitHub Actions while the monthly quota is exhausted.
7
+
8
+ ## Contract impact
9
+
10
+ The fallback is additive and does not change public schemas, metrics, release
11
+ gate meaning, existing CLI/API contracts, or the open-core boundary.
12
+
13
+ ## Acceptance evidence
14
+
15
+ | Gate | Result | Evidence |
16
+ | --- | --- | --- |
17
+ | Requirement and ADR | Pass | Requirements v2.2 and ADR 0019 |
18
+ | Fail-closed publication | Pass | Explicit `--yes`; PyPI also requires `PYPI_API_TOKEN` |
19
+ | 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
+ | 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 |
24
+
25
+ ## Limitations
26
+
27
+ - Local artifacts do not carry GitHub build-provenance attestation.
28
+ - Python-version matrix coverage is limited to locally installed interpreters.
29
+ - Security testing remains deferred by owner instruction.
@@ -0,0 +1,27 @@
1
+ # RAGOps v2.2.0 — quota-independent release fallback
2
+
3
+ RAGOps v2.2.0 adds a fully local release lane for periods when GitHub Actions
4
+ is unavailable or has exhausted its monthly quota.
5
+
6
+ ## Highlights
7
+
8
+ - Run Ruff, the full offline test suite, and deterministic PASS/BLOCK benchmark
9
+ checks locally before packaging.
10
+ - Build the wheel and source distribution once, with a reproducible CycloneDX
11
+ SBOM, SHA-256 manifest, and machine-readable local evidence.
12
+ - Create the annotated tag and GitHub Release directly through the authenticated
13
+ GitHub CLI without starting an Actions runner.
14
+ - Optionally promote the exact GitHub Release artifacts to PyPI with an explicit
15
+ project-scoped token; the operation fails closed when the token is absent.
16
+
17
+ ## Compatibility
18
+
19
+ This additive release changes no schema, evaluator meaning, gate threshold,
20
+ existing CLI command, API contract, or open-core boundary.
21
+
22
+ ## Known limits
23
+
24
+ Local PyPI publication cannot claim GitHub OIDC Trusted Publisher identity or
25
+ GitHub build provenance. The preferred Trusted Publishing workflow should be
26
+ restored when Actions capacity returns. Security testing remains deferred by
27
+ owner instruction.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ragops"
7
- version = "2.1.0"
7
+ version = "2.2.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"
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env python3
2
+ """Quota-independent release lane for RAGOps.
3
+
4
+ Build and validate locally, then publish the exact artifacts to GitHub and,
5
+ only with an explicitly supplied project-scoped token, PyPI.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ import hashlib
12
+ import json
13
+ import os
14
+ import shutil
15
+ import subprocess
16
+ import sys
17
+ import tomllib
18
+ from datetime import UTC, datetime
19
+ from pathlib import Path
20
+
21
+ ROOT = Path(__file__).resolve().parents[1]
22
+ DIST = ROOT / "dist"
23
+
24
+
25
+ def run(
26
+ *args: str,
27
+ env: dict[str, str] | None = None,
28
+ cwd: Path = ROOT,
29
+ ) -> None:
30
+ print("+", " ".join(args), flush=True)
31
+ subprocess.run(args, cwd=cwd, env=env, check=True)
32
+
33
+
34
+ def version() -> str:
35
+ data = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))
36
+ return str(data["project"]["version"])
37
+
38
+
39
+ def assert_tag(tag: str) -> str:
40
+ expected = f"v{version()}"
41
+ if tag != expected:
42
+ raise SystemExit(f"tag {tag!r} does not match package version {expected!r}")
43
+ if not (ROOT / "docs" / "releases" / f"{tag}.md").is_file():
44
+ raise SystemExit(f"missing release notes: docs/releases/{tag}.md")
45
+ return expected
46
+
47
+
48
+ def artifacts() -> list[Path]:
49
+ result = sorted(DIST.glob("ragops-*.whl")) + sorted(DIST.glob("ragops-*.tar.gz"))
50
+ if len(result) != 2:
51
+ raise SystemExit("expected exactly one wheel and one source distribution in dist/")
52
+ return result
53
+
54
+
55
+ def checksums(paths: list[Path]) -> Path:
56
+ manifest = DIST / "SHA256SUMS"
57
+ lines = [f"{hashlib.sha256(path.read_bytes()).hexdigest()} {path.name}" for path in paths]
58
+ manifest.write_text("\n".join(lines) + "\n", encoding="utf-8")
59
+ return manifest
60
+
61
+
62
+ def verify(tag: str) -> None:
63
+ assert_tag(tag)
64
+ run("ruff", "check", ".")
65
+ env = os.environ.copy()
66
+ env["PYTEST_DISABLE_PLUGIN_AUTOLOAD"] = "1"
67
+ run(sys.executable, "-m", "pytest", "-q", env=env)
68
+ run("ragops", "evaluate", "--scenario", "scenarios/japanese_troubleshooting/scenario.json",
69
+ "--responses", "scenarios/japanese_troubleshooting/sample_responses.json")
70
+ blocked = subprocess.run(
71
+ ["ragops", "compare", "--scenario", "scenarios/japanese_troubleshooting/benchmark-v0.2.json",
72
+ "--baseline", "scenarios/japanese_troubleshooting/benchmark-baseline.json", "--candidate",
73
+ "scenarios/japanese_troubleshooting/benchmark-regressed.json"], cwd=ROOT
74
+ )
75
+ if blocked.returncode != 2:
76
+ raise SystemExit(f"expected regression gate exit 2, got {blocked.returncode}")
77
+ shutil.rmtree(DIST, ignore_errors=True)
78
+ run(sys.executable, "-m", "build")
79
+ built = artifacts()
80
+ sbom = DIST / f"ragops-{version()}.cdx.json"
81
+ if shutil.which("cyclonedx-py"):
82
+ run("cyclonedx-py", "environment", sys.executable, "--output-reproducible",
83
+ "--output-file", str(sbom))
84
+ else:
85
+ raise SystemExit("cyclonedx-py is required: python -m pip install cyclonedx-bom==7.3.0")
86
+ manifest = checksums([*built, sbom])
87
+ evidence = {
88
+ "schema": "ragops-local-release-evidence-0.1",
89
+ "tag": tag,
90
+ "commit": subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip(),
91
+ "created_at": datetime.now(UTC).isoformat(),
92
+ "validation": "pass",
93
+ "trusted_publishing": False,
94
+ "artifacts": [path.name for path in [*built, sbom, manifest]],
95
+ }
96
+ (DIST / "LOCAL_RELEASE_EVIDENCE.json").write_text(
97
+ json.dumps(evidence, indent=2) + "\n", encoding="utf-8"
98
+ )
99
+
100
+
101
+ def github(tag: str, yes: bool) -> None:
102
+ assert_tag(tag)
103
+ if not yes:
104
+ raise SystemExit("publishing requires --yes")
105
+ paths = [*artifacts(), DIST / f"ragops-{version()}.cdx.json", DIST / "SHA256SUMS",
106
+ DIST / "LOCAL_RELEASE_EVIDENCE.json"]
107
+ if any(not path.is_file() for path in paths):
108
+ raise SystemExit("run verify first; release artifacts are incomplete")
109
+ run("git", "diff", "--quiet")
110
+ run("git", "diff", "--cached", "--quiet")
111
+ run("git", "tag", "-a", tag, "-m", f"RAGOps {tag}")
112
+ run("git", "push", "origin", tag)
113
+ run("gh", "release", "create", tag, *(str(path) for path in paths), "--verify-tag",
114
+ "--title", f"RAGOps {tag}", "--notes-file", f"docs/releases/{tag}.md")
115
+
116
+
117
+ def pypi(tag: str, yes: bool) -> None:
118
+ assert_tag(tag)
119
+ token = os.environ.get("PYPI_API_TOKEN")
120
+ if not yes or not token:
121
+ raise SystemExit("PyPI publish requires --yes and PYPI_API_TOKEN (project-scoped)")
122
+ release_dir = ROOT / ".local-release" / tag
123
+ shutil.rmtree(release_dir, ignore_errors=True)
124
+ release_dir.mkdir(parents=True)
125
+ run("gh", "release", "download", tag, "--dir", str(release_dir))
126
+ run("shasum", "-a", "256", "-c", "SHA256SUMS", cwd=release_dir)
127
+ distributions = sorted(release_dir.glob("ragops-*.whl")) + sorted(release_dir.glob("ragops-*.tar.gz"))
128
+ if len(distributions) != 2:
129
+ raise SystemExit("GitHub Release must contain exactly one wheel and one source distribution")
130
+ env = os.environ.copy()
131
+ env.update({"TWINE_USERNAME": "__token__", "TWINE_PASSWORD": token})
132
+ run(sys.executable, "-m", "twine", "upload", *(str(path) for path in distributions), env=env)
133
+
134
+
135
+ def main() -> None:
136
+ parser = argparse.ArgumentParser(description=__doc__)
137
+ sub = parser.add_subparsers(dest="command", required=True)
138
+ for name in ("verify", "publish-github", "publish-pypi"):
139
+ command = sub.add_parser(name)
140
+ command.add_argument("--tag", required=True)
141
+ if name != "verify":
142
+ command.add_argument("--yes", action="store_true")
143
+ args = parser.parse_args()
144
+ if args.command == "verify":
145
+ verify(args.tag)
146
+ elif args.command == "publish-github":
147
+ github(args.tag, args.yes)
148
+ else:
149
+ pypi(args.tag, args.yes)
150
+
151
+
152
+ if __name__ == "__main__":
153
+ main()
@@ -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.1.0"
6
+ __version__ = "2.2.0"
7
7
 
8
8
  __all__ = [
9
9
  "compare",
@@ -0,0 +1,31 @@
1
+ import importlib.util
2
+ from pathlib import Path
3
+
4
+
5
+ SPEC = importlib.util.spec_from_file_location("local_release", Path("scripts/local_release.py"))
6
+ assert SPEC and SPEC.loader
7
+ local_release = importlib.util.module_from_spec(SPEC)
8
+ SPEC.loader.exec_module(local_release)
9
+
10
+
11
+ def test_tag_must_match_package_version() -> None:
12
+ assert local_release.assert_tag(f"v{local_release.version()}") == f"v{local_release.version()}"
13
+
14
+
15
+ def test_checksum_manifest_is_deterministic(tmp_path, monkeypatch) -> None:
16
+ monkeypatch.setattr(local_release, "DIST", tmp_path)
17
+ artifact = tmp_path / "artifact.whl"
18
+ artifact.write_bytes(b"ragops")
19
+ manifest = local_release.checksums([artifact])
20
+ assert manifest.read_text().endswith(" artifact.whl\n")
21
+ assert len(manifest.read_text().split()[0]) == 64
22
+
23
+
24
+ def test_pypi_requires_explicit_token(monkeypatch) -> None:
25
+ monkeypatch.delenv("PYPI_API_TOKEN", raising=False)
26
+ try:
27
+ local_release.pypi(f"v{local_release.version()}", True)
28
+ except SystemExit as error:
29
+ assert "PYPI_API_TOKEN" in str(error)
30
+ else:
31
+ raise AssertionError("publish must fail closed without a token")
@@ -2,7 +2,7 @@ from ragops import __version__, responses_from_data, scenario_from_dict
2
2
 
3
3
 
4
4
  def test_stable_version() -> None:
5
- assert __version__ == "2.1.0"
5
+ assert __version__ == "2.2.0"
6
6
 
7
7
 
8
8
  def test_public_contract_parsers() -> None:
File without changes
File without changes