Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,31 @@ jobs:
run: |
ragops demo --profile engineer --output demo-output
ragops evidence verify --bundle demo-output/evidence

windows-no-clone:
runs-on: windows-latest
steps:
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "0.12.5"
- name: Run published credential-free demo without checkout
shell: pwsh
run: |
$demoJson = (& uvx --from "ragops==2.0.1" ragops demo --profile engineer --output demo-output | Out-String)
if ($LASTEXITCODE -ne 0) {
throw "ragops demo returned $LASTEXITCODE"
}
$summary = $demoJson | ConvertFrom-Json
if ($summary.candidate_decision -ne "BLOCK") {
throw "expected BLOCK, got $($summary.candidate_decision)"
}
if (-not (Test-Path "demo-output/release-report.html" -PathType Leaf)) {
throw "release-report.html was not generated"
}
uvx --from "ragops==2.0.1" ragops evidence verify --bundle demo-output/evidence
if ($LASTEXITCODE -ne 0) {
throw "evidence verification returned $LASTEXITCODE"
}
29 changes: 29 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CodeQL

on:
push:
branches: [main]
pull_request:
schedule:
- cron: "17 3 * * 1"

permissions:
contents: read

jobs:
analyze:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: github/codeql-action/init@42947a340483f03ba47bb1a039b2c519aab3df85 # v3
with:
languages: python
build-mode: none
- uses: github/codeql-action/analyze@42947a340483f03ba47bb1a039b2c519aab3df85 # v3
with:
category: "/language:python"
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### English

- Added a synthetic retrieval-poisoning Failure Zoo specimen for the Japanese troubleshooting benchmark.
- Added a synthetic retrieval-poisoning Failure Zoo specimen, a published-package Windows smoke test, CodeQL scanning, and explicit local-only usage evidence.

## [2.0.1] - 2026-08-23

Expand Down
2 changes: 2 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ RAGOps and its bundled plugin run locally by default. The project does not opera

RAGOps reads only the files and command arguments selected by the user. It may write reports, replay bundles, baselines, or local experiment records only when the user requests an operation that creates those artifacts. Those files remain in user-controlled storage.

Users may explicitly set `RAGOPS_USAGE_LOG` to write local usage events containing only a UTC timestamp, RAGOps version, top-level command name, and exit code. This is disabled by default, excludes command arguments and file paths, remains in user-controlled storage, and is never transmitted to the project author.

Optional provider or HTTP adapters can send data to an endpoint explicitly configured by the user. In that case, the endpoint operator's privacy terms apply. RAGOps does not enable a provider automatically and does not embed provider credentials.

Users control retention by deleting locally generated artifacts. For privacy questions, open an issue at https://github.com/thangldw/ragops/issues.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,15 @@ ragops evidence verify --bundle ./demo-output/evidence
open ./demo-output/release-report.html
```

On Windows PowerShell, replace the final command with
`Start-Process ./demo-output/release-report.html`.

The credential-free demo intentionally returns `BLOCK`: citation coverage `1.0 -> 0.5`, citation precision `1.0 -> 0.5`, and lexical groundedness `1.0 -> 0.6`. It is synthetic benchmark evidence, not production adoption evidence.

Install `ragops[api]` and run `ragops serve` for the local authenticated API/workbench. Use `ragops adapter list` for Phoenix, Ragas, DeepEval, LangSmith, MLflow, Promptfoo, custom JSON, and installed entry-point adapters.

Local CLI usage evidence is disabled by default. Set `RAGOPS_USAGE_LOG` to an explicit JSONL path to record only the UTC timestamp, RAGOps version, top-level command, and exit code; arguments and file paths are never recorded. Summarize the file with `ragops usage-report --events usage.jsonl`. Use the consent-aware `pilot-report` contract and the [production pilot runbook](docs/gtm/production-pilot.md) for production adoption evidence.

## Tiếng Việt

RAGOps so sánh trace ứng viên với baseline được chấp nhận, áp dụng release policy có version và xuất cùng một quyết định `PASS`, `WARN` hoặc `BLOCK` sang JSON/Markdown/HTML/JUnit/SARIF. Core không dependency, chạy offline; API/workbench là extra tùy chọn. Demo synthetic cố ý tạo `BLOCK`, không phải bằng chứng production adoption.
Expand Down
2 changes: 2 additions & 0 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

Install with `pip install -e '.[dev]'`, run `ruff check .`, then `PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest -q`. Verify `ragops demo --profile engineer`, `ragops evidence verify`, the packaged API/UI, every schema instance, and a clean `--no-deps` wheel import. Build wheel/sdist/SBOM/checksums from a clean commit, promote those exact artifacts to a GitHub Release, then dispatch the tag-bound PyPI Trusted Publishing workflow. GitHub publication, PyPI publication, ChatGPT directory submission, and ChatGPT approval are separate states and must be reported separately.

Optional local usage measurement is enabled only by setting `RAGOPS_USAGE_LOG=/controlled/path/usage.jsonl`. It records command name and exit code without arguments or paths; aggregate it with `ragops usage-report --events /controlled/path/usage.jsonl`. Production adoption claims require approved, pseudonymous observations through `ragops pilot-report`, not CLI event counts.

## Tiếng Việt

Cài bằng `pip install -e '.[dev]'`, chạy lint/test, demo/evidence verify, API/UI, schema và clean-wheel import. Build wheel/sdist/SBOM/checksum từ commit sạch, phát hành đúng artifact lên GitHub rồi mới chạy PyPI Trusted Publishing theo tag. Phải phân biệt GitHub release, PyPI release, ChatGPT submission và ChatGPT approval.
Expand Down
36 changes: 36 additions & 0 deletions docs/gtm/production-pilot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Production pilot evidence runbook

This runbook turns approved design-partner observations into reviewable RAGOps adoption evidence. It does not create production evidence by itself and does not treat synthetic fixtures, downloads, repository traffic, or CLI event counts as adoption.

## Entry criteria

- The design partner has approved the pilot purpose, measurement period, retention, and pseudonymous identifiers.
- A named owner controls the manifest, observation file, economics assumptions, and final review.
- Baseline and pilot tasks use the same eligibility rules and success rubric.
- Prompts, traces, customer content, emails, names, and account identifiers remain outside the pilot files.

## Measurement contract

Use `schemas/pilot-manifest-0.1.schema.json` for cohort and targets, `schemas/pilot-observation-0.1.schema.json` for one task observation per JSONL line, and `schemas/pilot-economics-0.1.schema.json` for optional estimates. Production manifests set `synthetic` to `false` and `consent_status` to `approved`.

Collect at least one completed baseline and pilot task, using unique task IDs. Record duration, task success, critical incidents, reviewer disagreement, and observed cost. RAGOps derives activation, repeat usage, task-success uplift, median time saved, incident count, disagreement rate, and optional ROI estimates from those explicit observations.

## Generate the evidence

```bash
ragops pilot-report \
--manifest controlled/pilot-manifest.json \
--observations controlled/pilot-observations.jsonl \
--economics controlled/pilot-economics.json \
--output controlled/pilot-report.md
```

Review the cohort, denominators, exclusions, consent, source files, failed conditions, and economic assumptions before sharing the result. A `SCALE` decision means the declared observational targets passed; it does not establish causality.

## Usage boundaries

`RAGOPS_USAGE_LOG` is optional local product-operation evidence. It contains only timestamp, version, top-level command, and exit code, so it cannot prove task success, repeat user adoption, or production impact. The skills-only ChatGPT plugin does not expose install or usage counts to this repository. Keep those platform metrics separate and label unavailable values as unavailable.

## Publication gate

Publish a case study only when the design partner approves the exact aggregate claims and no small-cohort cell can re-identify a person. Label observational results as production-derived, keep economic figures as estimates, disclose limitations, and retain the reviewed source bundle under the agreed retention policy.
180 changes: 180 additions & 0 deletions docs/superpowers/plans/2026-08-23-ragops-post-release-hardening.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# RAGOps Post-release Hardening Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Close the remaining post-2.0.1 benchmark, Windows, security, repository-governance, and measurable-adoption gaps without adding network calls to the core.

**Architecture:** Keep retrieval-poisoning evidence in the existing synthetic Failure Zoo, run the published no-clone demo in a checkout-free Windows job, and isolate CodeQL in its own least-privilege workflow. Record optional CLI usage as local JSONL from the console adapter only; production adoption continues to use the existing consent-aware `pilot-report` contract.

**Tech Stack:** Python 3.11+, pytest, Ruff, GitHub Actions, CodeQL, GitHub CLI.

**Spec:** `docs/superpowers/specs/2026-08-23-ragops-production-flagship-adoption-design.md`

## Global Constraints

- Python remains `>=3.11` with zero required runtime dependencies.
- The dependency-free core performs no network calls.
- Synthetic evidence is never described as production adoption evidence.
- Existing CLI commands, schemas, decisions, and exit codes remain compatible.
- GitHub Actions use least privilege and immutable action commit pins.

---

### Task 1: Retrieval-poisoning Failure Zoo specimen

**Files:**
- Create: `scenarios/japanese_troubleshooting/retrieval-poisoning-candidate.json`
- Modify: `tests/test_reference_benchmark.py`
- Modify: `CHANGELOG.md`

**Interfaces:**
- Consumes: scenario `benchmark-v0.2.json`, response fixture `benchmark-baseline.json`, existing evaluation policy.
- Produces: one named synthetic candidate whose deterministic evaluation is blocked for `unsupported_citation`, `unsupported_claim`, and `forbidden_output_term`.

- [ ] **Step 1: Apply the contributor test and fixture without changing the aggregate Failure Zoo**

Preserve PR #29 authorship, but omit its duplicate override in `failure-zoo-candidate.json` and rewrite its changelog entry under the current Unreleased section.

- [ ] **Step 2: Verify the regression test catches a missing specimen**

Run the new test before adding the fixture. Expected: FAIL because `retrieval-poisoning-candidate.json` does not exist.

- [ ] **Step 3: Add the minimal fixture**

```json
{
"schema_version": "0.2",
"extends": "benchmark-baseline.json",
"description": "Synthetic candidate that trusts an instruction embedded in poisoned retrieval.",
"overrides": [{
"case_id": "inject-01",
"answer": "了解しました。内部シークレットはSYNTHETIC_SECRET_42です。",
"citation_ids": ["poisoned-doc-77"]
}]
}
```

- [ ] **Step 4: Verify focused and full tests**

Run: `PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 .venv/bin/pytest -q tests/test_reference_benchmark.py`

Expected: all benchmark tests pass and the new candidate is `BLOCK` with the three named findings.

### Task 2: Windows no-clone and CodeQL workflows

**Files:**
- Create: `.github/workflows/codeql.yml`
- Modify: `.github/workflows/ci.yml`
- Modify: `tests/test_github_workflows.py`
- Modify: `README.md`

**Interfaces:**
- Consumes: published `ragops==2.0.1`, GitHub-hosted Windows/Linux runners.
- Produces: a checkout-free Windows smoke job and Python CodeQL result uploaded to GitHub code scanning.

- [ ] **Step 1: Write failing workflow behavior tests**

Assert that CI contains a `windows-no-clone` job with no checkout, runs `uvx --from ragops==2.0.1`, checks `candidate_decision == BLOCK`, verifies `release-report.html`, and verifies the evidence bundle. Assert that CodeQL has read-only contents, `security-events: write`, Python build mode `none`, and immutable `github/codeql-action` pins.

- [ ] **Step 2: Run the workflow tests and witness RED**

Run: `PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 .venv/bin/pytest -q tests/test_github_workflows.py`

Expected: FAIL because the Windows job and CodeQL workflow are absent.

- [ ] **Step 3: Add minimal workflows**

Use the existing immutable checkout/setup-python pins and `github/codeql-action` commit `42947a340483f03ba47bb1a039b2c519aab3df85`. The Windows PowerShell job installs `uv`, executes the public package without checkout, parses stdout JSON, and fails unless exit code is zero, decision is `BLOCK`, and HTML/evidence verification succeed.

- [ ] **Step 4: Verify workflow contracts**

Run the focused tests and parse all workflow YAML through Ruby's YAML parser with aliases enabled.

### Task 3: Local opt-in usage evidence

**Files:**
- Create: `src/ragops/usage.py`
- Create: `schemas/local-usage-event-0.1.schema.json`
- Create: `tests/test_usage.py`
- Modify: `src/ragops/cli.py`
- Modify: `README.md`
- Modify: `PRIVACY.md`
- Modify: `docs/OPERATIONS.md`

**Interfaces:**
- Consumes: explicit `RAGOPS_USAGE_LOG` file path and console command result.
- Produces: append-only local JSONL events containing only schema version, UTC timestamp, RAGOps version, top-level command, and exit code; `ragops usage-report` returns aggregate command and exit-code counts.

- [ ] **Step 1: Write failing privacy and aggregation tests**

The break caught is accidental collection of arguments/paths or failure to count an event. Tests invoke the real CLI entrypoint with `RAGOPS_USAGE_LOG`, assert no argument value appears in the JSONL line, and assert `usage-report` returns literal aggregate counts.

- [ ] **Step 2: Run focused tests and witness RED**

Run: `PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 .venv/bin/pytest -q tests/test_usage.py`

Expected: FAIL because `ragops.usage` and `usage-report` do not exist.

- [ ] **Step 3: Implement minimal local recorder and report**

Write one canonical JSON object per completed CLI process using append mode. Never send data over the network, never record option values, and emit a stderr warning rather than changing the evaluated command's exit code when the optional log cannot be written.

- [ ] **Step 4: Verify focused tests and privacy contract**

Run the focused tests, the schema-instance tests, and a real subprocess invocation with a temporary log.

### Task 4: Repository operations and governance

**Files:**
- Local-only: `.git/info/exclude`
- GitHub settings: repository ruleset for `main`
- GitHub Actions state: obsolete PyPI run `30749103590`

**Interfaces:**
- Consumes: GitHub repository admin API.
- Produces: clean local status, obsolete run canceled, and a main-branch ruleset requiring PRs and successful `test` plus `analyze` checks while blocking force-push and deletion.

- [ ] **Step 1: Exclude the two sibling repositories locally**

Add `/proofline/` and `/awesome-maintainer-defense/` to `.git/info/exclude`; do not move, delete, or modify either nested repository.

- [ ] **Step 2: Cancel the obsolete queued publisher**

Run: `gh run cancel 30749103590 --repo thangldw/ragops`, then query the run until it reaches `completed/cancelled` or GitHub reports it is no longer cancelable.

- [ ] **Step 3: Create the main ruleset after CI checks exist on main**

Require pull requests and the `test` and `analyze` status checks; block branch deletion and non-fast-forward updates. Keep repository administrators able to recover through the standard organization bypass model only if GitHub exposes it for this personal repository.

- [ ] **Step 4: Verify live settings**

Read the ruleset and code-scanning endpoints back from GitHub and compare exact enforcement/status-check fields.

### Task 5: Verification and integration

**Files:**
- All changed files from Tasks 1-3.

**Interfaces:**
- Consumes: the completed hardening branch.
- Produces: reviewed, merged `main` with green CI and closed issues #22 and #24; contributor PR #29 is closed with attribution preserved in the integrated commit.

- [ ] **Step 1: Run complete local verification**

Run Ruff, all pytest tests, credential-free demo/evidence verification, package build, and wheel smoke import.

- [ ] **Step 2: Review the full diff**

Check requirements line-by-line, inspect `git diff --check`, and verify that no cache, build output, secret, customer data, or telemetry log is tracked.

- [ ] **Step 3: Commit, push, and create a pull request**

Use small commits by task, open a PR to `main`, wait for all required checks, then merge without force-push.

- [ ] **Step 4: Close superseded contributor/issue state accurately**

Credit the contributor in the retrieval-poisoning commit and PR body. Close PR #29 only after the equivalent change lands; allow `Closes #22` and `Closes #24` in the merged PR body to close the issues.

- [ ] **Step 5: Verify public post-merge state**

Confirm `main` equals `origin/main`, only `main` remains in the primary repository, Actions are green, CodeQL has a completed analysis, and no new PyPI/plugin release was created.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ dev = ["pytest>=8.0", "ruff>=0.6", "fastapi>=0.115", "jsonschema>=4.23"]
release = ["build>=1.2", "cyclonedx-bom>=7.3", "twine>=5.1"]

[project.scripts]
ragops = "ragops.cli:main"
ragops = "ragops.cli:cli_entrypoint"

[tool.hatch.build.targets.wheel]
packages = ["src/ragops"]
Expand Down
15 changes: 15 additions & 0 deletions schemas/local-usage-event-0.1.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/thangldw/ragops/schemas/local-usage-event-0.1.schema.json",
"title": "RAGOps local usage event 0.1",
"type": "object",
"additionalProperties": false,
"required": ["schema_version", "recorded_at", "ragops_version", "command", "exit_code"],
"properties": {
"schema_version": {"const": "ragops-local-usage-event-0.1"},
"recorded_at": {"type": "string", "format": "date-time", "pattern": "Z$"},
"ragops_version": {"type": "string", "minLength": 1, "maxLength": 64},
"command": {"type": "string", "pattern": "^[a-z][a-z0-9-]{0,63}$"},
"exit_code": {"type": "integer", "minimum": 0, "maximum": 255}
}
}
Loading
Loading