oy-cli 0.13.0

Autonomous OpenCode agent and deterministic repository audit and review workflows
Documentation
# Examples and CI integration

These shortened examples show report shape and handoff semantics. Paths, IDs, model names, and findings are illustrative; actual model output is nondeterministic.

## Audit report with one finding

Command:

```bash
oy audit "authentication boundaries"
```

Representative `ISSUES.md` excerpt:

````markdown
# Audit Issues

> Generated by oy audit; model: provider/model; focus: authentication boundaries; max chunks: 80.

## Findings summary

- `audit-2a71...` **High** `src/auth.rs:84` — Session lookup accepts an unscoped tenant ID _(status: new; fix: `oy enhance audit-2a71...`)_

## Detailed findings

### [High] Session lookup accepts an unscoped tenant ID

Evidence: `src/auth.rs:84` uses the caller-provided tenant before authorization.

```json oy-findings
[
  {
    "id": "audit-2a71...",
    "status": "new",
    "source": "audit",
    "severity": "High",
    "title": "Session lookup accepts an unscoped tenant ID",
    "locations": [{"path": "src/auth.rs", "line": 84}],
    "evidence": "Caller-provided tenant reaches session lookup before authorization.",
    "body": "Bind tenant scope to the authenticated principal before lookup.",
    "category": "access-control"
  }
]
```
````

## Target-diff review

Command:

```bash
oy review main --focus "types and boundaries"
```

Representative `REVIEW.md` excerpt:

````markdown
# Code Quality Review

## Verdict

Needs work.

## Findings summary

- `review-7bd1...` **Medium** `src/cli/config.rs:41` — Two structs represent the same persisted state _(status: new; fix: `oy enhance review-7bd1...`)_

## Detailed findings

### [Medium] Two structs represent the same persisted state

The diff introduces a second source of truth. Keep one persisted type and convert at the boundary.

```json oy-findings
[{"id":"review-7bd1...","status":"new","source":"review","severity":"Medium","title":"Two structs represent the same persisted state","locations":[{"path":"src/cli/config.rs","line":41}],"evidence":"Both structs are serialized independently.","body":"Keep one persisted representation.","category":"state-ownership"}]
```
````

## No-findings report

The renderer still writes an explicit empty findings payload:

````markdown
# Code Quality Review

## Verdict

No major structural concerns.

## Findings summary

No high-conviction findings.

```json oy-findings
[]
```
````

This is distinct from a failed or incomplete run. Check the report transparency line and command exit status as well.

## One-finding remediation

```bash
oy enhance audit-2a71...
# Inspect the diff and verification output, then confirm:
oy audit "authentication boundaries"
```

The enhancer should change only one actionable finding and run focused verification. The next audit should omit the fixed finding or update its lifecycle state based on current evidence.

## SARIF output

```bash
oy audit --format sarif --out oy.sarif
```

The output is SARIF 2.1.0 with normalized rule IDs, locations, severity mapping, and oy metadata. Validate and inspect it before upload, especially when repository paths or finding bodies are sensitive.

## GitHub code scanning

An audit needs opencode plus provider credentials in the job. Use a protected environment/secret and avoid running untrusted pull-request code with privileged provider credentials.

```yaml
permissions:
  contents: read
  security-events: write

steps:
  - uses: actions/checkout@v4
  - name: Install oy and opencode
    run: |
      # Pin versions in production CI rather than installing mutable latest releases.
      cargo install oy-cli --locked --version 0.13.0
      mise use --global node@24 npm:@opencode-ai/cli@0.0.0-next-15353
      # Configure OpenCode authentication separately.
  - name: Run oy audit
    env:
      PROVIDER_API_KEY: ${{ secrets.PROVIDER_API_KEY }}
    run: oy audit --format sarif --out oy.sarif
  - name: Upload SARIF
    if: always() && hashFiles('oy.sarif') != ''
    uses: github/codeql-action/upload-sarif@v4
    with:
      sarif_file: oy.sarif
```

For other consumers, archive `oy.sarif` and ingest it with their SARIF 2.1.0 interface. oy does not upload reports itself.