Lenses
The eight built-in lenses, the four states every lens ends in, and how to write custom lenses.
A lens is a focused investigation of one concern, such as security or database safety. Each applicable lens investigates the pull request independently, gathers evidence, and ends in exactly one state. Warpway ships eight lenses; on the Team plan you can edit them and add your own.
The four states
| State | Key | Meaning | Effect on policy |
|---|---|---|---|
| Cleared | cleared | The required investigation was completed and no material concern remains. | Satisfies the lens. |
| Issue found | issue_found | A concrete, actionable defect or risk was identified, with code locations and evidence. | Blocks while a finding at a blocking severity is open. |
| Human decision required | human_decision_required | A material question remains that needs human judgment or organizational knowledge. | Blocks until the question is answered and the lens re-evaluated. |
| Incomplete | incomplete | Required work could not be completed: missing context or permissions, a tool or model failure, missing required evidence, or a failed verification run. | Blocks (fail closed). Never turned into Cleared. |
These effects are for required lenses. An optional lens blocks only through its blocking findings, its required questions or a sign-off it needs, or by being Incomplete when its findings could block and merge_gate.fail_on_incomplete is on.
Each result also states its coverage: what was investigated, what was not, and a coverage level of strong, moderate, weak or incomplete. Warpway does not present a lens's internal confidence as a probability that the change is safe.
Built-in lenses
| Lens | Key | Investigates | Default |
|---|---|---|---|
| Correctness | correctness | Logic errors, edge cases, error handling, concurrency where relevant, behavior that does not match the stated intent. | Required on every pull request |
| Security | security | Authentication, authorization, tenant isolation, injection, data exposure, secrets, trust boundaries, privilege escalation. | Required on every pull request |
| Testing / Reliability | testing | Coverage of changed behavior, failure paths, retries, race conditions, rollback and recovery, regression tests, CI results. | Required on every pull request |
| Architecture / Maintainability | architecture | Dependency boundaries, abstractions, coupling, duplication, your architecture conventions. | Advisory: warns, does not block |
| Backward Compatibility | compatibility | Public APIs, persisted data, schemas, events, SDKs, clients, rollout compatibility. | Required when the change touches APIs, SDKs, events, data models, schemas, migrations or configuration |
| Performance | performance | N+1 queries, memory growth, expensive loops, network calls, serialization, hot-path regressions. | Advisory: warns, does not block |
| Product Semantics | product_semantics | Whether behavior matches the ticket or specification, and whether a business decision is missing. | Required when the change touches business logic, billing, payments, UI, feature flags, API contracts or personal data |
| Database Safety | database_safety | Destructive migrations, locks, table rewrites, data loss, transaction semantics, rollout safety. | Required when the change touches migrations, SQL, schema files or the data model |
Product Semantics is the lens most likely to ask a non-engineer: when the intended behavior is not written down anywhere Warpway can read, it asks the product owner instead of guessing.
When a lens applies
A lens applies to a pull request when its applicability matches:
always: every eligible pull request;paths: any changed file matches one of these globs;categories: the change analysis tagged the pull request with one of these semantic categories;languages: any changed file is in one of these languages, by extension.
Files matching exclude_paths are ignored first, and so are files in review.ignore_paths; if every changed file is excluded, the lens does not apply.
A lens also runs when one of its rules or a conditional_lenses entry matches the change, even if its own applicability does not. A disabled lens never runs.
Being required does not change when a lens applies: a required lens must be resolved on every pull request it applies to, and does not run on the others. Correctness, Security and Testing apply to every pull request. To require a lens with narrower applicability everywhere, set its applicability to always; to require it only under another condition, use conditional_lenses.
Lens settings
| Setting | What it controls |
|---|---|
| Name and description | How the lens appears in GitHub, Slack and the dashboard. |
| Instructions | What the lens must check, in plain language. Built-in lenses come with detailed instructions you can extend. |
| Applicability | When the lens applies (above). |
| Required evidence | Evidence the lens must gather before it may conclude, such as callers_of_changed_code. Missing required evidence makes the lens Incomplete. |
| Tools | An allowlist narrowing which tools the lens may use. Text in the repository can never widen it. |
| Owners and routing | Who answers this lens's questions, and whether to prefer Slack. |
| Blocking | What the lens's findings do: block the merge gate (default), warn (shown but never block) or none (ignored). |
| AI clear | Whether the lens may be cleared by AI at trust level 3 (Clear) and above. When off, a person signs off on the lens when it is required. |
| Human sign-off | when_uncertain (default): an unresolved question creates a required task. never: questions are optional tasks; a required lens still waiting on an answer blocks unless merge_gate.require_all_required_lenses_resolved is off. always: a person signs off even when AI clears the lens, at every trust level. |
| Runtime profiles | Runtime verification profiles the lens needs. If a required profile cannot run, the lens is Incomplete. |
Tools
Lenses investigate with read-only tools scoped to one repository at one commit. They take no repository or organization parameters from the model, return bounded output, and record every call as evidence.
| Tool | Purpose |
|---|---|
read_file | Read a file at the reviewed commit. |
read_lines | Read a specific line range. |
list_directory | List a directory. |
search_text | Search the repository text. |
get_diff | The pull request's diff. |
get_file_diff | One file's diff. |
find_symbol | Find where a symbol is defined. Language-aware for TypeScript and JavaScript, text search elsewhere. |
find_references | Find callers and usages of a symbol, with the same fallback. |
get_commit_history | Commits that touched a path. |
get_blame | Who last changed lines, and in which commit. |
get_codeowners | CODEOWNERS entries for a path, from the base branch. |
get_related_tests | Tests related to a changed file. |
get_pr_comments | Comments and review comments on the pull request. |
get_previous_reviews | Earlier reviews of the pull request: GitHub review verdicts and earlier Warpway reviews. |
get_ci_status | CI check results on the head commit. |
get_linked_issues | Issues linked from the pull request, with their requirements. |
search_knowledge | Approved organization knowledge relevant to the change. |
No tool runs shell commands. Commands only run through runtime verification profiles you approve.
Custom lenses
On the Team plan, Admins can create, edit, clone and disable lenses in the dashboard, or define them in .warpway.yml. Every change to a custom lens's definition in the dashboard creates a new immutable version. Edits to built-in lenses, repository lens settings and lenses defined in .warpway.yml are captured in the policy version, and each review records the policy version and lens versions it used.
This lens from a healthcare team checks protected health information:
version: 1
lenses:
hipaa_phi:
name: HIPAA PHI Handling
applies_when:
paths:
- src/patient/**
- src/integrations/ehr/**
instructions:
- Confirm PHI is not written to application logs.
- Confirm access remains tenant-scoped.
- Confirm external processors are approved.
required_evidence:
- data_flow
- logging_paths
- external_services
routing:
slack_user_group: "@privacy"
human_signoff:
required_when_uncertain: trueTo build on a built-in lens instead of starting from scratch, use extends:
version: 1
lenses:
payments_security:
name: Payments Security
extends: security
applies_when:
paths:
- services/payments/**
instructions:
- Card data must never reach our servers; only Stripe tokens may be stored.
owners:
- "@acme/payments-security"
ai_clear: falseRules
Rules attach extra instructions to an existing lens for specific paths, without defining a new lens:
version: 1
rules:
- id: tenant-isolation
lens: security
applies_to:
paths:
- src/data/**
- src/api/**
instructions: >
Every access path to tenant-owned records must establish tenant
ownership before returning or mutating data.When a rule applies, its lens runs even if the lens would not otherwise apply. A rule without applies_to applies to every pull request. See rules for every field.
Organization knowledge
When a person's answer settles a question that will come up again, an Admin can save it as an organization rule, for example "Unused credits survive cancellation until natural expiration." Saved rules require explicit approval, keep their source (who answered, on which pull request), and can later be deprecated or superseded. Lenses retrieve only relevant knowledge, and any conclusion that relied on it cites it as evidence. See Human tasks.
Untrusted content
Repository files, pull request text, comments, tickets and Slack messages are treated as data, never as instructions. A comment that tells the reviewer to approve the change or ignore its instructions has no effect on the lens, and Security reports the attempt itself as an observation. See Security.
Something unclear or missing? Email marcus@cmglabs.ai.