The SDLC loop — six moments, and what runs at each
Where Vera fits in day-to-day development: the save, feature, PR, bug, morning and release loops, and exactly what executes at each one.
Vera is not a place you visit. It is six recurring moments in a working week, each with one command or one trigger. This page walks all six end to end, with the real commands, and says plainly which parts are not built yet.
Read the status column first. Two of the six loops are only partly shipped. Where something is planned but absent, this page says so in the same breath as the feature — a doc that describes an unshipped command as available is worse than no doc, because an agent will try to run it.
| # | Loop | Cadence | You run | Status |
|---|---|---|---|---|
| 1 | Save | every save | vera-agent watch --affected | Shipped |
| 2 | Feature | every feature | /vera:verify (or the MCP tools) | Shipped |
| 3 | PR | every PR | vera-agent check, then CI | Partly shipped — the triaged PR comment is not built |
| 4 | Bug | every bug | /vera:repro | Shipped |
| 5 | Morning | daily | nothing — radar + digest come to you | Shipped |
| 6 | Release | per release | — | Not built |
Command spelling. Every runnable line below is
npx vera-agent <cmd>. The package installs averabin alias too, sovera checkworks after a global install — butnpx verais not Vera: an unrelatedverapackage squats that name on npm. Copy thenpx vera-agentform.
Before the loops — wire the repo once
npx vera-agent init --url https://your-vera-host --token vera_your_tokenWrites .vera/config.json (commit it, no secrets), stores the token in
~/.vera/cli.json, registers the Vera MCP server for the directory, and adds an
agent-instructions block to AGENTS.md/CLAUDE.md. Idempotent.
Useful flags: --project <id>, --mcp-scope local|project (default local),
--no-mcp, --no-agents-md, --import <formats|all> / --no-import. The
importer turns an existing Cypress, Playwright, Postman, WDIO, Selenium,
TestCafe, HAR or OpenAPI suite into Vera tests deterministically — no AI, no key.
Running tests on your own machine (loops 1 and 3-local) additionally needs the enrollment token, which is a different species from the API token:
npx vera-agent login --url https://your-vera-host --token vera_agent_your_tokenFull walkthrough: getting-started.md.
1. Save loop
Trigger: every debounced file save. Owner: ENGAGEMENT G7.7.
npx vera-agent watch . --affectedOn each save it maps what you changed through the project's impact map and runs
exactly the impacted tests, in this process — seconds, not a queue round
trip, and it reaches http://localhost.
Options: --base <ref>, --tag <t> (pin those tests into every pass),
--max <n> (default 50 — over it the pass refuses and says so, it never
trims), --env <name>, --debounce <ms> (default 500), --verbose.
The bare
watch <dir>is the legacy path and behaves differently: it queues an org-wide tag match and drains it, selecting the same set on every save regardless of what you changed.--affectedis what makes this a save loop rather than a timer. See vera-check.md §12.
Needs both credentials — the vera_… API token to read the map, and the
vera_agent_… enrollment to run tests locally. Both are checked before the
watcher arms.
2. Feature loop
Trigger: your coding agent finished a change. Owner: ENGAGEMENT G3 + G4.
In Claude Code, with the plugin installed:
/vera:verifyThe agent runs what you just built in a real browser, as a captured auth role, on a named environment — credentials never enter the model's context — and the result persists as org run history with video, trace and screenshots.
This is the loop's whole point, and the honest framing matters: against a generic browser MCP, Vera is not competing to be "the agent's eyes". It wins on four things a generic browser tool cannot do — it runs as a real logged-in role, against a named environment, its results persist as shared history, and an observation can be promoted into durable coverage in one action.
The six plugin commands:
| Command | What it does |
|---|---|
/vera:verify | Verify a UI change by running it in a real browser as a real logged-in role |
/vera:check | Map the current change to the tests that cover it and the rules nothing protects |
/vera:cover | Add durable coverage for a goal, proposing the plan before authoring |
/vera:fix | Triage a red run and propose a repair before applying it |
/vera:repro | Turn a bug into a failing regression test |
/vera:status | Report what coverage exists and what is red or flaky |
Under them sit 33 MCP tools. The ones this loop uses most: inspect_page
(read real selectors before authoring), run_scenario (execute an unsaved step
list), save_scenario_as_test (promote it), get_failure_details,
suggest_fix / apply_repair. Repairs and saves are confirm-gated — Vera
proposes, you dispose. Full list: mcp.md; the skill and commands:
claude-plugin.md.
Without an MCP client, the same verification runs locally from the terminal:
npx vera-agent verify --project <projectId> --steps steps.json
npx vera-agent verify --test <testId>--steps takes a JSON file or - for stdin. Also --env, --role, --label,
--json. Exit 0 pass / 1 fail / 2 no run.
3. PR loop
Trigger: you are about to push. Owner: ENGAGEMENT G7 (shipped) + G10 (not built).
Before the PR — locally
npx vera-agent checkReads your diff — the base range plus staged, unstaged and untracked files, because the main user has not committed yet — and maps it onto the tests that cover it and the rules nothing protects. Read-only. Deterministic: three code-level joins and heuristics, no AI, so it needs no BYOK key and burns no AI grant.
npx vera-agent check --run # run exactly the impacted set, server-side
npx vera-agent check --run --local # run them here instead, so they reach localhost
npx vera-agent affected src/checkout.ts # reverse lookup: what covers this one fileDefault --run is server-side, in the cloud, regardless of the project's run
target. --local executes in this process via the bundled runner.
Other flags: --base <ref>, --files <a,b,c> (skip git), --with-always-run,
--env <name>, --timeout <s> (default 1800), --json, --always-run-tag.
Exit codes — 0 clean · 1 usage/config · 2 could not complete · 3 a
test failed · 4 --strict found a gap. Precedence when several apply is
3 › 2 › 4 › 0.
An empty impacted-test list means the map is blind, not that your change is safe. Read vera-check.md §4 and §6 before trusting a quiet report on a new project.
In CI
- uses: actions/checkout@v4
with:
fetch-depth: 0 # load-bearing — a shallow clone resolves no base
- name: Impacted tests
run: npx vera-agent check --base origin/${{ github.base_ref }} --run
env:
VERA_API_URL: ${{ vars.VERA_API_URL }}
VERA_PROJECT_ID: ${{ vars.VERA_PROJECT_ID }}
VERA_TOKEN: ${{ secrets.VERA_TOKEN }}Add --strict once the project shows non-zero map coverage; it fails the job
(exit 4) when the diff touches an uncovered rule, and never fires on
"partial". Turning it on before coverage exists just teaches people to ignore it.
To run the whole suite against a preview deploy instead, use the vera-run
action, which gates the job on real failures and treats quarantined and
passed-on-retry tests as warnings (ci-integration.md). To
execute runs on your own runners, use the vera-agent-ci action
(ci-rider.md).
What is NOT built: the triaged PR comment
A sticky, pre-triaged pull-request comment does not exist. Posting the impact report back onto the PR — with per-failure app-bug / test-bug / flake classification and deep links — is planned as ENGAGEMENT G10 and is not shipped.
What exists today: vera-agent check --run [--strict] is a CI step that passes
or fails and prints to the job log. The vera-run action additionally writes a
GitHub job summary. Neither posts a PR comment. If you want something richer
now, build it on --json, which emits one machine-readable document on stdout
(progress goes to stderr) carrying the full report, per-test results, exitCode
and exitReason, plus which base was used.
4. Bug loop
Trigger: a bug is filed. Owner: ENGAGEMENT G6.
/vera:reproDescribe the bug and it files the issue, then proposes a failing regression test that reproduces it. You approve before anything is saved or run — the propose→approve contract holds here as everywhere.
Over MCP the same path is report_issue → generate_repro_test →
approve_repro_test, plus list_issues / update_issue for triage. The
generate step needs AI (your own key); filing and triage do not.
The point of the loop: a bug that produced a regression test cannot silently come back, and the issue and the test stay linked.
5. Morning loop
Trigger: a schedule. Owner: ENGAGEMENT G8 + G9. You run nothing.
Three shipped pieces:
App-change radar (G8). On a timer, Vera crawls the project's own origin,
fingerprints each page's structure, and diffs it against the last baseline.
Deterministic — no AI. Fingerprints hash structural identity only (tag, type,
role, name, data-testid/id), so a pure copy edit produces no change row.
It navigates only; it never clicks, because on an authenticated app a button
reading "Accept" can be a destructive confirmation. Each change gets a
disposition — unreviewed | expected | suspect — and accepting one advances the
baseline, so the feed can actually reach zero. Live at
Project → Radar, or over MCP as get_app_changes.
Staged repair proposals (G9). When a changed element intersects a test's selectors, Vera dry-runs that test and, on failure, stages a repair proposal for review. Propose-only: approving is what applies it, and approval writes the repair audit.
One gardener per project. A project with auto-repair on keeps the shipped auto-applying behaviour and is skipped by the proposal path, so no test is handled twice. The review queue names that state rather than rendering an empty list.
Daily digest (G9.4). Changed pages, at-risk tests and rules, staged repairs, and new-page coverage suggestions, through the notifications hub. Silent when nothing is unreviewed — no-news genuinely means no message. Opt-in per org, and org-wide by construction (a project-scoped digest rule is refused).
An org with no AI configured still gets the radar and the at-risk list — only staged repairs need AI, and the UI says so.
6. Release loop
Trigger: cutting a release. Owner: ENGAGEMENT G12.
Not built
There is no ship-gate command and no ship-gate verdict. A single ship/no-ship
answer composed from suite status, the impact report over the release diff, open
critical issues and the flake budget is sketched as ENGAGEMENT G12 and is
not shipped. release-check is not a command — the CLI does not accept it.
There is also, deliberately, no README status badge and no weekly digest — both were cut from the plan rather than deferred.
What you can genuinely do at release time today, with shipped pieces:
# the impact report over the whole release diff, as a gate
npx vera-agent check --base <last-release-tag> --run --strictThat gives you one exit code over the release range (3 › 2 › 4 › 0), plus
--json for the detail. It is not a composed verdict: it does not read open
issues or the flake budget, and it will not tell you why in one line. Treat it
as a check, not a gate.
What we measure, and what we deliberately do not
Every machine surface records one counter row per deliberate action —
{workspace, surface, action, user, time} — where surface is mcp (an agent
tool call), api (a token-authed CI/CLI request) or cli (a deliberate
vera-agent command). It counts behaviour, never spend, and nothing reads it
to refuse anything. The agent-lease long-poll is excluded on purpose: it ticks on
a timer, so it would measure uptime rather than usage.
Platform admins see this at /admin → Engagement.
Answerable from the counters:
| Metric | How |
|---|---|
| Scenario runs per week | run_scenario (MCP) + verify:steps (CLI), in trailing 7-day buckets. verify:test is excluded — it runs a saved test, not a scenario. |
| Scenario→test conversion | save_scenario_as_test ÷ MCP scenario runs. The denominator is MCP-only on purpose: a local vera verify --steps has no promotion counter, so including CLI runs would understate conversion. |
| Which tools get repeated | Per-tool and per-command counts with last-used time. |
| Surface mix, active workspaces | Events per surface; distinct workspaces. |
Not answerable — and shown as omissions rather than guesses:
- % of PRs with a Vera check. No pull request, repository or commit is recorded, and Vera never sees the denominator (how many PRs a repo opened). Only the number of check calls is countable, which is a different quantity.
- Time to first green. No run outcome is in the counters. It is measured
properly — from run rows, on
/admin→ Overview — so read it there. - Weekly triage actions. Triage happens in the dashboard, and no dashboard action is counted; the only surfaces are MCP, API and CLI. Counting the MCP triage tools alone would measure agents, not people.
- Runs per active developer. Only personal tokens carry a user id. Org-wide tokens record none, and the CLI surface records none at all — so the panel shows the run count and the unattributed count side by side, and refuses to print a per-developer ratio it cannot honestly compute.
Plans
| Surface | Needs |
|---|---|
MCP tools on /api/mcp | Free (mcp-basic) |
/api/v1 — check, check --run, CI API | Pro (api-access) |
| App-change radar | Pro (app-radar) |
| Digest / alerts | Pro (notifications) |
| Cross-project chains | Team (chains) |
A free cloud workspace gets 401 on /api/v1 — the CLI says exactly that rather
than printing a bare 401 — while the MCP tools keep working. Self-hosted and
local installs have no billing: every feature is on.
See also
- Getting started —
init, the config files, first green - Change impact (
vera check) — the three joins and their honest limits - MCP server — every tool, auth, the confirm-to-apply rule
- Claude Code plugin — the skill and the
/vera:*commands - Local agent — running tests on your own machine
- CI integration · CI-rider