sieve

module
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: Apache-2.0

README

sieve

A zero-infra, provider-agnostic PR reviewer. One static Go binary — no server, no container, no docker pull. Runs as a GitHub Action or a CLI, with your own model API key.

sieve PR review release

sieve fetches a PR, parses its diff into an exact line-anchor model, filters noise, sends batched prompts to the LLM provider of your choice, anchor-validates every finding against the real diff, routes survivors through a two-tier noise gate, and posts them as one editable walkthrough comment plus a batched inline review. Re-runs edit in place and never duplicate comments. Writes require an explicit switch (--post, or post: true in the Action); no config key can enable them.

Quickstart — GitHub Action (≈ 5 minutes)

  1. Add your model key as a repo secret named SIEVE_API_KEY (Settings → Secrets and variables → Actions).
  2. Commit .github/workflows/sieve.yml:
name: sieve
on: { pull_request: { types: [opened, synchronize, reopened, ready_for_review] } }
permissions: { pull-requests: write, contents: read }
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: gnanam1990/sieve@v0
        with: { provider: anthropic, model: claude-sonnet-4-6 }
        env:
          SIEVE_API_KEY: ${{ secrets.SIEVE_API_KEY }}
          GITHUB_TOKEN: ${{ github.token }}

That's it — open a PR and sieve reviews it. The action downloads the pinned, checksum-verified sieve binary for the runner and runs sieve review --post.

  • Fork PRs are detected and skipped cleanly (secrets are unavailable to them) — see docs/forks.md. Same-repo PRs are the supported surface.
  • Exit code 2 (a truncated diff or a failed inline post) is a warning, not a CI failure, unless you set fail_on_partial: true.
  • The API key is read from the env var named by api_key_env_name (default SIEVE_API_KEY) — it is never an action input, because inputs are echoed to logs.
Workflow templates

Copy a ready-made template into .github/workflows/ from .github/workflows/templates/:

  • sieve.yml — Anthropic Claude (default).
  • sieve-openrouter.yml — OpenRouter/Qwen (budget-friendly).
Action inputs
Input Default Notes
provider anthropic anthropic | openai-compat | fake
model required (except fake), e.g. claude-sonnet-4-6
base_url required iff provider: openai-compat
api_key_env_name SIEVE_API_KEY name of the env var holding the key (not the key)
config_path .sieve.yml your review-scope + gate config; a provider block is appended only if it has none
post true false = review without writing
version (VERSION file) sieve release to download; @v0 resolves the matching binary
fail_on_partial false fail the job on exit 2
sarif_files path to write a SARIF v2.1.0 report, e.g. sieve.sarif
verify_signatures false require a valid cosign signature for the downloaded binary
Marketplace

sieve PR review is published on the GitHub Marketplace. Use gnanam1990/sieve@v0 to stay on the latest stable major version.

Install the CLI

# Homebrew
brew install gnanam1990/tap/sieve

# curl installer (downloads + checksum-verifies the latest release binary)
curl -fsSL https://raw.githubusercontent.com/gnanam1990/sieve/v0/install.sh | bash

# Go
go install github.com/gnanam1990/sieve/cmd/sieve@latest

Or from a checkout: make build. Requires Go 1.23+. No CGo. sieve version prints the build version, commit, date, Go version, and platform.

Quickstart — CLI

export GITHUB_TOKEN=ghp_...        # or --token
export ANTHROPIC_API_KEY=sk-ant-...
cat > .sieve.yml <<'EOF'
provider:
  type: anthropic
  model: claude-sonnet-5
EOF
sieve review --repo owner/name --pr 123          # review, findings on stdout
sieve review --repo owner/name --pr 123 --post   # …and post to the PR
  • stdout — deterministic JSON ReviewContext including Findings and the Gate block (tier per finding, drop/demote counters, fingerprints)
  • stderr — human summary: file table, findings table, token usage footer

--dry-run skips the LLM pass entirely (stage-1 behavior: context dump only). --json-only suppresses the stderr summary (combinable with --post). Exit codes: 0 ok · 2 partial (truncated context, a failed batch, or a failed inline post) · 1 error.

Offline / local review

Review a local git worktree without a GitHub token or App PEM. sieve reads git diff <base>...HEAD, builds the same ReviewContext, and runs the same pipeline. --post is not allowed because there is no PR; SARIF and JSON output work normally.

# on a feature branch, base is origin/main or main
sieve review --local --base main
sieve review --local --base main --sarif sieve.sarif

When --repo is omitted, the repo name is inferred from origin or the directory name (used only for summary/SARIF output). --local still requires a model key unless you use provider: fake or --dry-run.

SARIF output (GitHub Security tab)

sieve review --sarif sieve.sarif writes findings in SARIF v2.1.0 format. Upload them with github/codeql-action/upload-sarif:

sieve review --repo owner/name --pr 123 --sarif sieve.sarif

In a workflow:

- uses: gnanam1990/sieve@v0
  with:
    provider: anthropic
    model: claude-sonnet-5
    sarif_files: sieve.sarif
  env:
    SIEVE_API_KEY: ${{ secrets.SIEVE_API_KEY }}
- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: sieve.sarif
    category: sieve

Only active findings (inline + notes) are included; resolved findings are intentionally omitted because SARIF describes current issues.

FAQ: is there a Docker image?

No — and that's the point. sieve is a single static binary with no runtime dependencies; the Action downloads it directly (a few MB, checksum-verified and cosign-signed) and runs it. A container would add a docker pull, a registry, and image-scanning overhead to buy nothing.

License

Apache-2.0.

Draft PRs are skipped (exit 0, empty findings) unless review.review_drafts: true — this holds even with --post: a draft is never written to.

Posting to the PR (--post)

sieve review --repo owner/name --pr 123 --post

runs the full review, then routes surviving findings through the noise gate and writes them to the PR:

  • One walkthrough comment — created on the first run, edited in place on every later run (located by a hidden marker). It carries a stats line, a table of the top-tier findings, collapsible Notes / Resolved / Skipped sections, and a hidden metadata block that makes cross-run dedupe stateless.
  • Inline review comments for the top tier only, submitted as one review (a single notification), with committable ```suggestion blocks where a finding carries a safe one.
  • Cross-run dedupe — re-running never duplicates an inline comment. Findings that disappear are listed under Resolved since last review.
The --post safety model
  • Posting is enabled only by the --post flag. There is no config key for it — a committed .sieve.yml can never turn writes on. A post: key anywhere in config is a hard error.
  • Every GitHub write goes through one package (internal/post); a test greps the tree to prove no other package touches a mutating endpoint.
  • --post and --dry-run are mutually exclusive.
  • The GitHub client resolves its token through a TokenSource (today a static flag/env token; a GitHub App installation token later) — environment access stays confined to the command layer.
The noise gate

Findings are routed by confidence and severity:

review:
  min_confidence: 0.6         # drop floor: below this a finding is discarded (counted)
  inline_min_confidence: 0.8  # inline tier requires confidence >= this
  inline_min_severity: major  # inline tier requires severity >= this (major | critical)
  max_inline_comments: 10     # hard cap on inline comments per run (1-30)

The pipeline, in order: within-run dedupe (overlapping same-category findings collapse to the highest-confidence one) → floor (drop below min_confidence) → tier routing (inline needs both gates; everything else surviving the floor becomes a walkthrough note) → cap (inline beyond max_inline_comments is demoted to notes, never dropped) → cross-run dedupe (findings already posted last run are not re-posted inline). inline_min_confidence must be >= min_confidence. Without --post, the gate still runs and its decisions appear in the JSON Gate block — only the writing is gated.

Walkthrough anatomy
<!-- sieve:walkthrough -->                          ← locator marker (find + edit in place)
<!-- sieve:meta v1 <base64 json> -->                ← hidden state: head SHA + fingerprints
## sieve review
**2 findings** · 3 notes · 1 resolved · 6 files reviewed, 2 skipped   ← stats

| Severity | Finding | Where |                       ← top-tier (inline) findings only
|---|---|---|
| 🔴 critical | SQL built by string concatenation | `internal/db/query.go:88` |
| 🟠 major | Unchecked error from Close | `internal/gh/client.go:141` |

<details><summary>📝 Notes (3)</summary> … </details>        ← lower tier, grouped by file
<details><summary>✅ Resolved since last review (1)</summary> … </details>
<details><summary>⏭️ Skipped files (2)</summary> … </details>

<sub>model `…` · tokens in 18.2k / out 1.4k · sieve <version></sub>   ← footer

Severity markers: 🔴 critical · 🟠 major · 🟡 minor · ⚪ nit. The comment is kept under GitHub's 65,536-char limit by truncating Notes, then Resolved, then Skipped — the metadata block is never truncated.

Incremental re-review

After the first review, a push re-reviews only the files that changed since the last walkthrough (GET compare/<last>...<head>); every other finding is carried forward from the metadata unchanged, keeping its inline thread. A finding whose anchored line no longer exists in the diff is resolved at zero model cost. sieve falls back to a full review on a force-push/rebase (the base SHA is no longer an ancestor), an unchanged head SHA, a first run, or --full — the reason is in Stats.FullReviewReason, and Stats.TokensSaved estimates what the delta avoided. Toggle with review.incremental (default on).

Learning from outcomes

sieve keeps a local, append-only outcome log per repo under ${XDG_DATA_HOME:-~/.local/share}/sieve/<host>/<owner>/<repo>/events.jsonl: what it found, what got fixed, and how people reacted (👍/👎 and resolved threads). Writes are best-effort — they never fail a review. GitHub stays the source of truth: sieve sync --repo o/r --pr N rebuilds the log from the PR alone (idempotent), so the store is disposable.

sieve stats --repo owner/name          # per-category addressed-rate, 👍/👎, confidence
sieve learnings --repo owner/name      # draft repo rules from repeated 👎/dismissals

sieve learnings clusters findings maintainers repeatedly rejected and drafts one suppressive rule per cluster (one imperative sentence, generalized — no line numbers, PR refs, or verbatim code), writing them into .sieve/learnings.md under a <!-- sieve:learnings --> marker (your own notes above the marker are preserved) and printing a diff. It never commits — you review and commit the rules yourself. This is deliberate: repo rules change what the bot flags, so a human must approve them; sieve makes no bot commits, ever. When .sieve/learnings.md is present at the PR head, its rules are injected into the review prompt (capped at 8 KB) and the walkthrough footer notes learnings: N rules active.

Confidence calibration (opt-in)

With review.calibration: true, sieve scales each finding's confidence by its category's addressed-rate from the local store — clamp(addressed_rate/0.5, 0.5, 1.0), a no-op below a 10-finding sample — before the gate. It's transparent: the JSON records raw vs calibrated per finding and the footer notes calibration: on. Default off; never silently on.

GitHub Action note

The store lives on the runner's ephemeral filesystem. To let learnings and stats accumulate across Action runs, cache it with actions/cache keyed on the repo:

- uses: actions/cache@v4
  with:
    path: ~/.local/share/sieve
    key: sieve-store-${{ github.repository }}

Losing the cache is harmless — sieve sync rebuilds it from the PR.

Provider configuration

API keys are never written in config. .sieve.yml holds the name of an environment variable (api_key_env); sieve reads the key from there at run time. An api_key: field in config is a hard error.

Anthropic
provider:
  type: anthropic
  model: claude-sonnet-5
  api_key_env: ANTHROPIC_API_KEY
OpenAI
provider:
  type: openai-compat
  model: gpt-5.2
  base_url: https://api.openai.com/v1
  api_key_env: OPENAI_API_KEY
OpenRouter
provider:
  type: openai-compat
  model: qwen/qwen3-coder-next
  base_url: https://openrouter.ai/api/v1
  api_key_env: OPENROUTER_API_KEY
Kimi
provider:
  type: openai-compat
  model: kimi-for-coding
  base_url: https://api.kimi.com/coding/v1
  api_key_env: KIMI_API_KEY

Kimi's API requires temperature: 1 for kimi-for-coding; lower values are rejected. The fingerprint that drives cross-run "Resolved since last review" excludes the title, so rephrased findings with the same anchor line are no longer mis-reported as resolved+new. If the model also re-anchors the finding (changes the reported start line), the fingerprint will still change; this is a model consistency issue, not a fingerprint issue.

Groq
provider:
  type: openai-compat
  model: llama-4.1-70b
  base_url: https://api.groq.com/openai/v1
  api_key_env: GROQ_API_KEY
Ollama (local)
provider:
  type: openai-compat
  model: qwen3-coder
  base_url: http://localhost:11434/v1
  api_key_env: OLLAMA_API_KEY   # Ollama ignores the value; set e.g. OLLAMA_API_KEY=ollama

base_url is required for openai-compat — there is no default, so requests never go somewhere you didn't name. Knobs: max_tokens (256–32768, default 4096), temperature (0–1, default 0.1), timeout_seconds (10–600, default 120, per request). Retries: 429/5xx/Anthropic-overloaded are retried up to 3 attempts with backoff + jitter, honoring Retry-After.

Multi-model pipelines

By default sieve runs one model as the reviewer (the single pipeline). For higher precision you can name several providers and route them into a judge or ensemble pipeline.

The providers map

Give each model a name under providers:, then point review.roles at those names:

providers:
  fast:
    type: openai-compat
    model: qwen/qwen3-coder-next
    base_url: https://openrouter.ai/api/v1
    api_key_env: OPENROUTER_API_KEY
  strong:
    type: anthropic
    model: claude-sonnet-5
    api_key_env: ANTHROPIC_API_KEY

review:
  pipeline: judge
  roles:
    generator: fast    # proposes liberally
    judge: strong      # verifies against the code, drops the weak ones

The legacy single provider: block still works and is equivalent to a providers.default entry with review.roles.reviewer: defaultno migration needed to keep your current config. Setting both provider: and providers: is a hard error. To migrate by hand, move the provider: block under providers: as a named entry and select it with a role.

Pipeline selection guide
Pipeline What it does Cost Use when
single one reviewer the default; fast and cheap
judge a liberal generator proposes, a second model verifies each finding against the code (may lower severity/confidence or drop, never invents a more-severe finding) ~1.6× you want fewer false positives without paying for a strong model on every token — the recommended upgrade
ensemble 2–3 reviewers run independently; only findings ≥2 of them agree on survive 2–3× experimental; you want a recall/precision study, not day-to-day CI

Measured on the seeded sandbox (testdata/sandbox). The first three rows used local Ollama kimi-k2.7-code:cloud — the same model for every role, so the judge could not benefit from a stronger verifier. The last row is a hosted-model validation with Kimi kimi-for-coding.

Pipeline Recall Precision Input tokens Output tokens Wall time Notes
single (Ollama) 10/10 10/10 4,597 3,106 ~45 s baseline
single/fast (Ollama) 10/10 10/10 4,597 3,923 ~47 s same model, max_tokens: 4096
judge (Ollama) 10/10 10/10 12,595 7,705 ~103 s generator 9,147/7,193 + judge 3,448/512
single (Kimi hosted) 10/10 10/10 4,594 2,098 ~55 s kimi-for-coding via api.kimi.com

The Ollama judge row is not cheaper than single because the verifier uses the same model as the generator. The expected win (~1.6× cost vs single/strong) requires a cheap fast generator plus a strong, concise judge; the Kimi single row confirms hosted-model end-to-end behavior.

Judge pipeline

The generator is prompted to be liberal — propose every plausible issue — and the judge verifies each candidate against the same diff the generator saw, returning a keep/drop verdict with a recalibrated confidence and (never raised) severity. Malformed judge output triggers one corrective retry; a second failure fails open (the generator's findings pass through untouched) because the noise gate still stands downstream. Dropped findings are recorded in the JSON output for transparency, and the walkthrough footer shows per-role tokens and pipeline: judge.

Ensemble pipeline (experimental)

⚠️ Experimental, 2–3× token cost. Ensemble runs the whole review 2–3 times. For almost every real use case the judge pipeline gives you better precision per token — prefer it. Ensemble exists for measuring agreement, not for cheap CI.

review:
  pipeline: ensemble
  roles:
    ensemble: [fast, strong, other]   # 2..3 members

Findings agree when they share a path, category, and diff side with lines within ±3 (or overlapping ranges). Agreement clusters backed by ≥2 distinct members survive, carrying the highest-confidence member finding plus the cluster's mean confidence (EnsembleMean in JSON).

Cost guardrail

review.max_run_tokens (optional, 0 = unlimited) refuses a run whose pre-flight token estimate — the batched prompt bytes over ~4 bytes/token, times the pipeline multiplier (single 1×, judge 1.6×, ensemble n×) — exceeds the cap. It exits 1 before calling any provider, so a surprise-large PR can't quietly run up a judge/ensemble bill.

Self-hosting (daemon mode)

Prefer to run it yourself instead of per-repo Actions? sieve serve is a single-binary daemon: point a GitHub App's webhooks at one small VPS, bring your own keys, and it reviews every PR — App auth, a signature-verified webhook receiver, and a crash-safe coalescing queue, in ~one process.

sieve serve --config /etc/sieve/server.yml

Providers are server-owned — a repo's .sieve.yml may tune review settings (min_confidence, excludes, …) but never the model or keys, so an untrusted repo can't choose your spend. Full walkthrough (GitHub App setup, systemd unit, reverse-proxy TLS): docs/self-hosting.md. Example config + unit file live in deploy/.

Findings schema

Each finding in Findings[]:

Field Meaning
Path changed file the finding is anchored to
Line / EndLine anchor line(s); NewNum for RIGHT, OldNum for LEFT; EndLine 0 = single line
Side RIGHT (new file) or LEFT (old file), GitHub Reviews API vocabulary
Severity critical | major | minor | nit
Confidence model-reported calibrated probability 0..1; the noise gate filters and tiers on it
Category bug | security | perf | correctness | test | style
Title one line, ≤120 chars
Body markdown: why + fix
Suggestion optional replacement code; rendered as a committable ```suggestion block when safe

Anchor gate: every finding is validated against the parsed diff — the path must be a kept file and the line(s) must be commentable on the claimed side within a single hunk. Findings that fail are dropped (never repaired) and counted in Stats.FindingsDropped. This is the anti-hallucination gate: a comment that would land on the wrong line is worse than no comment.

Output ordering is deterministic: severity, then path, then line. Stats reports FindingsTotal, FindingsDropped, BatchesFailed, Requests, Retries, InputTokens, OutputTokens, and InlinePostFailed (inline comments that failed to post under --post). The Gate block reports per-finding tier + fingerprint and the gate counters (FindingsBelowFloor, InlineDemotedByCap, DuplicatesMerged, RepeatedInline, ResolvedCount, …).

Review scope controls

review:
  include_file_content: true # attach full file contents to prompts when small
  max_file_content_kb: 64    # per-file attachment cap
  concurrency: 3             # parallel provider calls (1-8)
  review_drafts: false

Prompts are greedy-packed into batches of ≤24k estimated input tokens (bytes/4). A single file exceeding the whole budget is truncated hunk-by-hunk and marked TruncatedForReview in the output.

Testing with the fake provider

For offline runs and CI, type: fake returns a canned response instead of calling any API — not for real use:

provider:
  type: fake
  fixture: path/to/canned-response.json   # file content is returned verbatim

The fixture should contain the same JSON contract a real model returns: {"findings": [...]}. Findings still go through the anchor gate, so a fixture with stale line numbers gets dropped — which makes it a good test of the gate itself.

Default excludes

Applied before configured globs; binary files are always skipped. Every skip is reported with its reason.

Category Patterns
Vendored / build output vendor/, node_modules/, dist/, build/, .next/, target/ (any depth)
Minified / derived *.min.js, *.min.css, *.map
Generated code *.pb.go, *_generated.go, *.gen.go
Lockfiles package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb, go.sum, Cargo.lock, poetry.lock, Pipfile.lock, composer.lock, Gemfile.lock
Snapshots *.snap
Images / fonts / archives png jpg jpeg gif webp ico woff woff2 ttf eot zip gz tar

go.mod is deliberately not excluded — dependency changes are reviewable; go.sum is noise.

Repository context (Stage 8)

sieve can attach lightweight, structured repository context to the prompt header. Depth is controlled by review.context_depth:

Depth What is sent Best for
symbols (default) Extracted symbols (functions, types) from the changed files only fast, safe default; no local checkout needed
repomap Repo-wide symbol/import index, capped by context_max_files understanding cross-file structure
blast Repomap limited to direct + indirect files around the change targeted impact surface
review:
  context_depth: symbols        # symbols | repomap | blast
  context_max_files: 20         # cap files in repomap/blast (0 = unlimited)
  context_max_tokens: 8000      # rough token budget for context
  context_langs: [go, c, cpp]    # empty = all languages

The CLI passes the current working directory as the repo root, so repomap and blast work out of the box. In GitHub Actions and daemon mode there is no checkout on the review path, so repomap/blast fall back to symbols quietly.

Context is rendered under # Repository context in the prompt and is counted against the pre-flight token budget.

Suppressing findings

Maintainers can tell sieve to drop known-acceptable findings by committing .sieve/ignore.yml in the repo root:

ignore:
  - fingerprint: abc123...          # exact sieve fingerprint
    reason: accepted race in legacy path
    expires: 2026-12-31             # optional; rule is ignored after this date
  - category: style                 # match any style finding
    reason: generated files are not styled
    path: "**/*.pb.go"              # optional path glob
  - severity: nit
    reason: nits are handled separately

Matchers:

Field Match
fingerprint exact sieve fingerprint (replaces an existing rule with the same fingerprint)
path glob with * (one segment) and ** (any segments); leading ! negates
category exact category string
severity exact severity string
title substring of the finding title

Multiple fields on the same rule are ANDed. A finding is ignored if any active rule matches. expires is parsed as YYYY-MM-DD in UTC.

Add a rule from the CLI without editing YAML by hand:

sieve ignore --fingerprint FP --reason "accepted"
sieve ignore --category style --path "**/*.pb.go" --reason "generated"
sieve ignore --title "nil pointer in test" --severity nit

The command writes to .sieve/ignore.yml in the current worktree and never auto-commits. It preserves any hand-written preamble above a # sieve:ignore marker. Use --file to target another path.

Suggested ignore rules

When a maintainer down-votes a sieve inline comment or resolves its review thread without a fix, sieve records that signal in the local outcome store. The next sieve review --post (or daemon/Action run) surfaces a collapsible Suggested ignore rules section in the walkthrough footer with the exact CLI command to list them:

sieve ignore --suggest --repo owner/name

To apply a suggested rule to the worktree:

sieve ignore --apply-suggestion 0 --repo owner/name

Suggested rules default to a 90-day expiry; use --no-expiry to keep one permanent. The suggestion path is read-only — no rule is applied or committed automatically.

Interactive TUI

sieve tui is a local, terminal-based interface for browsing reviews without posting anything to GitHub:

sieve tui                          # pick from recent projects or start a review
sieve tui --repo owner/name --pr N
sieve tui --local --base main

Inside the TUI you can navigate findings, down-vote them, add suppression rules to .sieve/ignore.yml, view locally-suggested rules, and save the full review JSON report. Everything stays on your machine: the feedback is written to the same per-repo local store used by sieve stats and sieve learnings.

Ignored findings are dropped after fingerprint decoration but before the confidence floor and tier routing. The walkthrough footer reports the count, and the CLI summary prints ignored separately so suppressed findings remain visible rather than silent.

Limits

  • Diff fetch capped at 5 MB (truncated at the last complete file boundary); GitHub caps file listings at 3000 files. Either sets Truncated and exit code 2.
  • PR description is truncated to 2 KB in prompts.

Development

make test    # go test ./... -race -shuffle=on
make lint    # golangci-lint
make cover   # gates: diff/findings/gate >= 90%, fingerprint 100%, post/render/provider >= 85%, overall >= 85%
make golden  # regenerate parser, prompt, render, and E2E golden files

scripts/sandbox_recall.sh runs the live calibration gate: it creates a private sandbox PR under your account with ~10 planted issues and runs --post with a frontier model (needs ANTHROPIC_API_KEY or OPENROUTER_API_KEY). See STAGE_NOTES.md for the recorded results.

Dependency policy: yaml.v3, doublestar, go-cmp (tests only), malivvan/tree-sitter (wazero-backed C/C++ grammar parsing), and tetratelabs/wazero (WASM runtime for grammars). GitHub REST and all LLM APIs are spoken via stdlib net/http. No streaming, no SSE: blocking completion calls with per-request timeouts.

Directories

Path Synopsis
cmd
sieve command
Command sieve is a zero-infra, provider-agnostic PR reviewer.
Command sieve is a zero-infra, provider-agnostic PR reviewer.
internal
blast
Package blast computes a blast radius from a repo map and a set of changed files.
Package blast computes a blast radius from a repo map and a set of changed files.
config
Package config loads and validates .sieve.yml.
Package config loads and validates .sieve.yml.
diff
Package diff parses git unified diffs into an exact line-anchor model.
Package diff parses git unified diffs into an exact line-anchor model.
filter
Package filter decides which files of a PR are worth reviewing.
Package filter decides which files of a PR are worth reviewing.
findings
Package findings defines the review finding schema, response parsing, anchor validation against the parsed diff, and deterministic sorting.
Package findings defines the review finding schema, response parsing, anchor validation against the parsed diff, and deterministic sorting.
fingerprint
Package fingerprint computes content-anchored identifiers for findings so posting can be deduplicated across runs.
Package fingerprint computes content-anchored identifiers for findings so posting can be deduplicated across runs.
gate
Package gate is the noise gate: it turns the raw, anchor-valid findings of a review into two posting tiers (inline vs walkthrough notes) plus a list of findings resolved since the last run.
Package gate is the noise gate: it turns the raw, anchor-valid findings of a review into two posting tiers (inline vs walkthrough notes) plus a list of findings resolved since the last run.
gh
Package gh is a minimal read-only GitHub REST v3 client for the handful of endpoints sieve needs.
Package gh is a minimal read-only GitHub REST v3 client for the handful of endpoints sieve needs.
gh/appauth
Package appauth mints GitHub App installation tokens: it signs a short-lived RS256 JWT with the app's private key, exchanges it for a per-installation access token, and caches that token (with single-flight refresh) until shortly before it expires.
Package appauth mints GitHub App installation tokens: it signs a short-lived RS256 JWT with the app's private key, exchanges it for a per-installation access token, and caches that token (with single-flight refresh) until shortly before it expires.
grammar
Package grammar runs tree-sitter language parsers inside a pure-Go wazero runtime.
Package grammar runs tree-sitter language parsers inside a pure-Go wazero runtime.
ignore
Package ignore loads and matches repository-level suppression rules so sieve can drop findings a maintainer has already reviewed and accepted.
Package ignore loads and matches repository-level suppression rules so sieve can drop findings a maintainer has already reviewed and accepted.
ignore/suggest
Package suggest turns negative review outcomes into concrete ignore-rule proposals for .sieve/ignore.yml.
Package suggest turns negative review outcomes into concrete ignore-rule proposals for .sieve/ignore.yml.
incremental
Package incremental decides how much of a re-review a run needs: a full re-review, or a delta that re-reviews only the files changed since the last posted walkthrough and carries the rest of the active findings forward.
Package incremental decides how much of a re-review a run needs: a full re-review, or a delta that re-reviews only the files changed since the last posted walkthrough and carries the rest of the active findings forward.
learnings
Package learnings turns sieve's own negative outcomes (👎 reactions and dismissed threads) into repository-specific review rules.
Package learnings turns sieve's own negative outcomes (👎 reactions and dismissed threads) into repository-specific review rules.
local
Package local reads a git worktree diff and metadata so sieve can review a local branch without a GitHub token or App PEM.
Package local reads a git worktree diff and metadata so sieve can review a local branch without a GitHub token or App PEM.
memory
Package memory is sieve's local, append-only outcome store: a JSONL event log per repository under the user's data dir.
Package memory is sieve's local, append-only outcome store: a JSONL event log per repository under the user's data dir.
metrics
Package metrics provides a minimal Prometheus-compatible metrics registry for sieve serve.
Package metrics provides a minimal Prometheus-compatible metrics registry for sieve serve.
post
Package post performs every GitHub write sieve makes: creating or editing the single walkthrough comment and submitting the inline review.
Package post performs every GitHub write sieve makes: creating or editing the single walkthrough comment and submitting the inline review.
prompt
Package prompt assembles the system and per-batch user prompts and greedy-packs files into token-budgeted batches.
Package prompt assembles the system and per-batch user prompts and greedy-packs files into token-budgeted batches.
provider
Package provider defines the single-shot LLM completion abstraction and the shared retry decorator.
Package provider defines the single-shot LLM completion abstraction and the shared retry decorator.
provider/anthropic
Package anthropic adapts the Anthropic Messages API to the provider interface.
Package anthropic adapts the Anthropic Messages API to the provider interface.
provider/fake
Package fake is a deterministic provider for tests and offline E2E runs.
Package fake is a deterministic provider for tests and offline E2E runs.
provider/openai
Package openai adapts any OpenAI-compatible chat-completions endpoint (OpenAI, OpenRouter, Groq, local Ollama) to the provider interface.
Package openai adapts any OpenAI-compatible chat-completions endpoint (OpenAI, OpenRouter, Groq, local Ollama) to the provider interface.
queue
Package queue is the daemon's persistent, coalescing review queue.
Package queue is the daemon's persistent, coalescing review queue.
render
Package render turns gate results into the markdown sieve posts: the single walkthrough comment (with its hidden metadata block) and the inline review comment bodies, including committable suggestion blocks.
Package render turns gate results into the markdown sieve posts: the single walkthrough comment (with its hidden metadata block) and the inline review comment bodies, including committable suggestion blocks.
repomap
Package repomap builds a repo-wide symbol and import index from source files.
Package repomap builds a repo-wide symbol and import index from source files.
review
Package review assembles the ReviewContext for a PR: metadata + parsed diff + filter decisions.
Package review assembles the ReviewContext for a PR: metadata + parsed diff + filter decisions.
sarif
Package sarif converts sieve findings into the Static Analysis Results Interchange Format (SARIF) v2.1.0 so they can be uploaded to GitHub's Security tab via github/codeql-action/upload-sarif or consumed by other SARIF-aware tools.
Package sarif converts sieve findings into the Static Analysis Results Interchange Format (SARIF) v2.1.0 so they can be uploaded to GitHub's Security tab via github/codeql-action/upload-sarif or consumed by other SARIF-aware tools.
server
Package server is sieve's daemon: it validates a server.yml, wires GitHub App auth, the webhook receiver, and the persistent review queue, and runs the review pipeline per job against an installation token.
Package server is sieve's daemon: it validates a server.yml, wires GitHub App auth, the webhook receiver, and the persistent review queue, and runs the review pipeline per job against an installation token.
symbols
Package symbols extracts declarations and references from source files for richer review context.
Package symbols extracts declarations and references from source files for richer review context.
tui
Package tui is sieve's interactive, local terminal UI.
Package tui is sieve's interactive, local terminal UI.
version
Package version holds build metadata, stamped at release time via ldflags:
Package version holds build metadata, stamped at release time via ldflags:
webhook
Package webhook is the daemon's HTTP front door: it verifies GitHub webhook signatures (constant-time, before any parsing), dedupes redeliveries, and turns pull_request events into review jobs.
Package webhook is the daemon's HTTP front door: it verifies GitHub webhook signatures (constant-time, before any parsing), dedupes redeliveries, and turns pull_request events into review jobs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL