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.
- {ragops-2.1.0 → ragops-2.2.0}/CHANGELOG.md +8 -0
- ragops-2.2.0/NEXT_SESSION.md +195 -0
- {ragops-2.1.0 → ragops-2.2.0}/PKG-INFO +1 -1
- ragops-2.2.0/docs/architecture/adr/0019-local-release-fallback.md +22 -0
- ragops-2.2.0/docs/engineering/local-release.md +32 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/pypi-publishing.md +3 -3
- ragops-2.2.0/docs/product/requirements-v2.2.md +24 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/program-completion-audit.md +2 -2
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v2.1-acceptance.md +6 -4
- ragops-2.2.0/docs/project/v2.2-acceptance.md +29 -0
- ragops-2.2.0/docs/releases/v2.2.0.md +27 -0
- {ragops-2.1.0 → ragops-2.2.0}/pyproject.toml +1 -1
- ragops-2.2.0/scripts/local_release.py +153 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/__init__.py +1 -1
- ragops-2.2.0/tests/test_local_release.py +31 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_public_api.py +1 -1
- {ragops-2.1.0 → ragops-2.2.0}/.dockerignore +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/design-partner.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/evaluator.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/ISSUE_TEMPLATE/feature.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/pull_request_template.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ci.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/nightly.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/pages.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/publish-pypi.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ragops-gate-smoke.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ragops-gate.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/ragops-pr-comment.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.github/workflows/release.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/.gitignore +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/AGENTS.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/CODE_OF_CONDUCT.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/CONTRIBUTING.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/Dockerfile +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/LICENSE +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/README.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/SECURITY.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/SUPPORT.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/apps/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/apps/api/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/apps/api/main.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/apps/github_pr_comment.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/apps/web/index.html +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/compose.yaml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/design-qa.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0001-local-first-core.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0002-baseline-regression-gates.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0003-reference-app-outside-core.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0004-open-core-boundary.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0005-scenario-0.2-metadata-and-citation-precision.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0006-response-fixture-overlays.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0007-offline-reference-graphrag-agent.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0008-local-team-review-workflow.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0009-adopt-mit-license.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0010-repair-trace-04-schema-json.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0011-reusable-pr-gate-is-an-adapter.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0012-opentelemetry-export-is-an-example-adapter.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0013-additive-demo-catalog-and-codepoint-budget.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0014-separate-pr-evaluation-from-comment-publication.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0015-portable-design-partner-measurement.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0016-first-class-evaluator-gates.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0017-api-authentication-and-input-bounds.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/adr/0018-portable-external-metric-envelope.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/component-diagram.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/context-diagram.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/control-plane-alpha.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/data-model.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/pr-comment-publishing.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/system-overview.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/architecture/threat-model.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/cv-linkedin-copy.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/01-current-desktop.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/02-implementation-desktop.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/04-implementation-mobile.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/06-desktop-comparison.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/09-limitations-section.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/design-audit/selected-open-source-adoption.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/infographics/evidence-stack.svg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/infographics/release-gate-flow.svg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/portfolio-case-study.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/portfolio-handoff.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/presentation-outline.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-limitations-screen.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-mobile-screen.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-portfolio-desktop.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-portfolio-mobile.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-release-screen.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/screenshots/ragops-showcase-hero.jpg +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/social-preview.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/video-script.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/demo/walkthrough.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/01-start.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/02-pass-decision.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/03-invalid-json-stale-decision.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/04-fixed-pass-decision.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/05-fixed-invalid-json.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/design-audit/v1.9/workbench-audit.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/export-your-first-trace.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/github-pr-gate.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/gitlab-ci-gate.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/handbook.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/observability.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/provider-adapters.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/engineering/testing-strategy.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/answer-length-budget.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/benchmark-report-v0.2.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/evaluator-gates.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/red-team-plan.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/scenario-taxonomy.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/evaluation/strategy.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/examples/github-pr-comment.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/examples/gitlab-ci-ragops.yml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/getting-started.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/design-partner-outreach.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/design-partner-pilot-runbook.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/github-launch-checklist.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-fixtures/synthetic-economics.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-fixtures/synthetic-manifest.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-fixtures/synthetic-observations.jsonl +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/pilot-measurement-plan.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/gtm/synthetic-pilot-report.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/commercialization.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/competitive-analysis.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/jobs-to-be-done.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/oss-launch-plan.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/personas.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/product_thesis.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v0.1.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v0.2.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.5.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.6.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.7.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v1.8.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v2.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/requirements-v2.1.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/roadmap.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/product/success-metrics.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/backlog.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/charter.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/decision-log.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/m1-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/m2-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/m3-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/m4-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/m5-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/milestones.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/release-plan.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/risk-register.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.5-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.6-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.7-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v1.8-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/v2.0-acceptance.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/project/work-breakdown.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.5.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.6.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.7.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v1.8.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v2.0.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/docs/releases/v2.1.0.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/README.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/agent.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/architecture.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/cli.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/data/documents.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/data/graph.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/discovery.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/executive-report.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/results/comparison.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/results/graph-traces.jsonl +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/results/lexical-traces.jsonl +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/rollout-plan.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/scenario.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/japanese_troubleshooting_agent/suite.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/README.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/adapter.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/examples/opentelemetry_trace_adapter/spans.jsonl +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/ragops.toml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/attack-pack.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-adversarial.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-baseline.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-regressed.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/benchmark-v0.2.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/evaluation-policy.toml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/external-metric-policy.toml +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/external-metrics-baseline.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/external-metrics-candidate.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/regressed_responses.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/sample_responses.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/sample_traces.jsonl +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/scenarios/japanese_troubleshooting/scenario.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/attack-pack-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/external-metrics-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/pilot-economics-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/pilot-manifest-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/pilot-observation-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/report-0.2.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/response-fixture-0.2.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/responses-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/scenario-0.1.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/scenario-0.2.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/trace-0.3.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/schemas/trace-0.4.schema.json +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/site/apple-touch-icon.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/site/favicon.png +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/site/index.html +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/site/styles.css +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/skills/ragops-feature/SKILL.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/skills/ragops-presentation/SKILL.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/skills/ragops-release/SKILL.md +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/adapters/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/adapters/external_metrics.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/adapters/http.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/benchmarks.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/cli.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/config.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/control_plane.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/demo.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/engine.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/evaluators.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/loader.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/models.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/pilot.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/plugins.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/providers/__init__.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/providers/openai_responses.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/reporters.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/store.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/src/ragops/traces.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_adoption_recipes.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_answer_length_cli.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_api_contract.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_benchmarks.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_comparison.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_config.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_control_plane.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_demo.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_engine.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_evaluator_depth.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_external_metrics.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_github_workflows.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_http_adapter.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_loader.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_openai_provider.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_opentelemetry_adapter.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_pilot.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_plugins_and_traces.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_pr_comment_publisher.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_readme_visuals.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_reference_agent.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_reference_benchmark.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_release_version.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_response_fixtures.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_scenario_v02_and_attacks.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_schema_files.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_showcase_site.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_store_and_html.py +0 -0
- {ragops-2.1.0 → ragops-2.2.0}/tests/test_team_workflow.py +0 -0
- {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.
|
|
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.
|
|
12
|
+
- Current verified release: `2.1.0`
|
|
13
13
|
- GitHub environment: `pypi`
|
|
14
14
|
- Publisher: `thangldw/ragops`, workflow `publish-pypi.yml`
|
|
15
|
-
- Verification: 2.
|
|
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.
|
|
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 |
|
|
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.
|
|
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
|
-
**
|
|
6
|
-
|
|
7
|
-
|
|
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 |
|
|
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.
|
|
@@ -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()
|
|
@@ -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")
|
|
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
|