Skip to content

AI product manager + AI QA

Every test starts with a real bug.

Somebody reports a bug. Shrike finds the cause, proves it, and keeps the test forever.

one real bug
Larkfield
staging.larkfield.example/reports/tenants

Tenants report

01 Aug – 31 AugRun
TenantUnitRent

audit log

Shrike

  • Bug reported by email“the tenants report downloads empty”09:14
  • Read your codeexports/tenant_report.py:18409:14
  • You clickedFile it + prove it09:16
  • Opened the staging siteno fix exists yet09:16
  • Signed in09:16
  • Opened the tenants report09:17
  • Asked you which buttonIt can re-aim a click. It can never re-aim a check.09:17
  • Picked 01–31 August09:17
  • Ran the report09:17
  • Expected some rows — got none09:17
  • Bug reproducedbug reproduced09:17
  • Fix checked twice. Test kept.09:18
Answer Shrike…send
video 00:19 every step trace
A worked example against a fictional app. Not recorded footage.

never writes to your code·staging unless you override it·a person approves everything

The gap

The bug report and the test never meet.

A bug report is the best information you will ever get about how your product breaks.

It gets read once, turned into a ticket, and thrown away.

  • Testing tools start from nothing

  • Triage tools stop at the ticket

The product side

It keeps the inventory of what you have built.

A feature registry, synced out of your Jira board and your git history. Every row carries the issue keys and the commit SHAs that put it there.

And the weekly digest is not written by a model. It is those rows, rendered.

A quiet week renders as “nothing shipped”. It will not invent a list to fill the space. Available as an email digest to your principals, and as Excel or PowerPoint — off until you switch it on.

feature registryjira + git
  • ExportsTenant report CSVLF-2231 · 7f3a91cshipped
  • ExportsMonth-boundary range fixLF-4418in progress
  • AdminSecond admin inviteLF-4402planned
  • BillingLegacy prorationLF-1180deprecated

rows come from your board · not from a model

Where it comes from
Synced from your Jira board and your git history. Not a spec doc you have to maintain.
What it holds
Name, area, status, shipped date, Jira keys, commit SHAs, PR URLs, owner.
What it answers
Do we have X? What shipped last week? Where did this feature come from?
How it reads
Read-only. It never asks anyone for a status update, and never writes to Jira on its own.

The loop, as a diagram

plate 01 — one bug, end to endscroll →
01Reportedby email02Investigatedread-only · cited03Approvedby a person04Reproducedbefore any fix05Keptruns every deployfile:line · commit · issuefile it + prove itexpected rows · got 0
the only failure anyone wantsstep 04

The loop

One bug, all the way through.

Five steps. A person decides at step three.

  1. 01Bug reported
  2. 02Cause found, with sources
  3. 03You approve
  4. 04Test proves it
  5. 05Kept forever
  1. 01intake

    The bug arrives.

    Somebody emails what broke. No portal, no form. Shrike sorts it and spots the duplicates.

    reported todayone mailbox
    • 09:14Tenants report downloads emptysorted · exports
    • 09:26August export is blanksame bug as above
    • 10:02Can’t invite a second adminasked for more detail

    no portal · no form · they just email what broke

  2. 02investigate

    It reads your code.

    Read-only. Every sentence it writes has to point at a line of code, a commit, or a ticket.

    investigation · LF-4417read-only

    The export filter drops every row when the requested range crosses a month boundary.

    exports/tenant_report.py:184commit 7f3a91c

    Introduced by the range-clamp change shipped for the billing rollout.

    exports/filters.py:63LF-2231
    authorClaude Opus2 claims written
    verifierGPT-5agrees · 2/2
    verifierGemini Proagrees · 2/2
    gatedeterministic1 uncited claim dropped

    no citation, no claim — the gate is code, not a model

  3. 03decide

    You press the button.

    File it, ask the reporter something, escalate, merge, or reject. Nothing happens on its own.

    review email · LF-4417awaiting a person

    AI-generated — validate before acting

    • Raise a Jira ticket
    • Raise ticket + record the bug
    • Ask the reporter a question
    • Escalate to an advisor
    • Merge as duplicate
    • Reject

    nothing filed · nothing emailed · nothing activated

  4. 04reproduce

    It proves the bug.

    The test runs before anyone writes a fix. It fails on camera, and that failure is the proof.

    run #1 · before any fixchromium · staging
    tenants_export_spans_month_boundarybug reproduced
    1. 1sign in as the QA analyst accountok
    2. 2open /reports/tenantsok
    3. 3set range 01 Aug – 31 Augok
    4. 4expect rows > 0received 0
    confirmed on re-run 2/2 video 00:19 timeline trace
    jira LF-4418 · “QA BUG REPRODUCED: tenants export empty across month boundary”
  5. 05verify

    It checks the fix.

    The same test runs again. Still failing means nobody is told it is fixed.

    verification · LF-4417same test, unchanged
    run #2 · fix 9c41be2still failing
    • “your bug is fixed” email withheld
    • evidence returned to the review team
    run #3 · fix a77d10fpassed
    • reporter told, with the evidence
    • kept in the suite · runs on every deploy

    the suite grows by one real failure, not one guess

A year in, your tests are a map of how this product really breaks.

Workflows

Set the rule once. It runs itself after that.

You still decide — you just decide when you write the rule, instead of every time a bug lands.

Nothing runs that you did not switch on.

Staging only, and read-only on your code.

Every run leaves the same evidence behind.

workflowon
  1. whena bug arrives in the mailbox
  2. thenreproduce it on staging
  3. andopen a Jira issue with the video and the trace attached
  4. whenthe fix is deployed
  5. thenrun the same test again
  6. andpost pass or fail on the issue, with the evidence

one rule · every bug that matches it

Day one

You don’t wait for something to break.

Starting from bugs sounds like starting from zero. It isn’t. We read the bugs you have already closed and turn the ones that still matter into tests.

So the suite opens as a record of how this product has already broken — not an empty folder.

seeded from closed ticketsjira
  • LF-1180Invite link expired too earlytest kept
  • LF-1204Rent total wrong across a month endtest kept
  • LF-1233Duplicate tenant on fast double-submittest kept

your history is the starting suite

Trust

Still trusted in six months.

Teams don’t abandon tests because they stop working. They abandon them because they can’t tell which failures are real.

reported on a repeat

A failure has to happen twice.

A first failure queues a confirming re-run. Only a repeat is reported, so the suite does not train people to ignore it.

our fault stays ours

error is not failed.

A locked test account or an unreachable site is our problem — never reported as a bug in your product.

blast radius

Nothing risky is kept.

Tests are stored as data, not code. Credentials are injected per run and masked in stored step detail. Staging, unless you override it.

It can re-aim a click. It can never re-aim a check.

If a button got renamed, Shrike asks which one you meant — once — and remembers. But it can never quietly change what a test is checking for.

Every run is filmed.

Video, the steps it took, console errors, failed requests, full trace.

Capabilities

The awkward parts, handled.

The things that decide whether you still trust it next year.

  • Video
  • Every step
  • Console errors
  • Failed requests
  • Full trace
Reported only on a repeat
A first failure queues a confirming re-run instead.
error is not failed
Our outage is never your bug.
No test code stored
Tests are data, so editing one can never run code.
Credentials injected at run time
Substituted per run, masked in stored step detail.
Staging only
Production is refused unless you override it yourself.
Filmed every time
Video, steps, console, network, full trace.
Asks when unsure
A renamed button gets one question, then it remembers.
Checks are not re-aimed
A click can be re-aimed. What a test asserts cannot.
Published claims carry a source
A line of code, a commit, or a ticket.
Three models, one gate
Two others check the first one’s work. The gate is code.
Read-only on your code
It looks. It never writes.
Duplicates merge
The same bug twice stays one ticket.

If you leave

What you keep, and the one thing you don’t.

“No stored test code” is a security property. It should not turn into a hostage situation, so here is exactly what stays yours.

The tests

Every case as validated JSON operations.

The write-ups

Each one is already a comment on your Jira board — on your board, not ours.

The evidence

Videos, timelines and traces sit in your own R2 bucket the whole time.

There is no Playwright export today. The cases are JSON operations, and nothing in the product turns them back into spec files. If that is a dealbreaker, say so now rather than in month six.

Grounding

It can’t publish a claim it can’t source.

Every sentence needs a source. No source, no sentence.

claims proposed3
  • The export drops every row when the range crosses a month.

    exports/tenant_report.py:184commit 7f3a91c
  • It broke in the change shipped for billing.

    exports/filters.py:63LF-2231
  • Probably broken since March.

    no source
write-up published2
  • The export drops every row when the range crosses a month.

    exports/tenant_report.py:184commit 7f3a91c
  • It broke in the change shipped for billing.

    exports/filters.py:63LF-2231
  • every claim sourced

author

Claude Opus

verifier

GPT-5

verifier

Gemini Pro

gate

deterministic · no model

How the gate works.

Three models, not one.
One writes it. Two others check it against the same code, separately.
The gate is code.
Plain software throws out anything unsourced. No model gets a vote.
Dropped, not softened.
An unsourced sentence doesn’t get hedged. It doesn’t appear.

Where your code goes

Three vendors see the excerpts. You can make it one.

Cross-checking only means something if the other models read the same sources. So every configured verifier gets the same rendered excerpts — the exact file:line snippets in the write-up.

Configure one key instead of three and only that vendor ever sees them. You lose the cross-check, and the gate then caps every claim at Unverified — no verifiers means no consensus. That is the trade, stated plainly, and it is yours to make.

all three keys setdefault
  • AnthropicClaude Opuswrites the investigation
  • OpenAIGPT-5checks it against the same excerpts
  • GoogleGemini Prochecks it against the same excerpts
cross-checkedexcerpts leave your network to all three
one key setyour call
every claim cappedone vendor · no consensus · unverified

Control

A human always decides.

Shrike suggests. You choose — case by case, or once in a workflow rule. Nothing runs that you did not switch on.

AI-generated — check before acting

on every write-up, every time

File the ticket
just files it
File it + prove it
files it and runs the test now
Ask a question
goes back to whoever reported it
Escalate
for the calls you want a human to make
It’s a duplicate
folds into the open one
Reject
closed, with the reason kept

one click each · all of them wait for a person

Integrations

Works where your team already is.

  • Gmail

    report a bug

  • Outlook

    report a bug

  • Jira

    tickets and cases

  • Playwright

    drives Chromium

  • Git

    commits and history

  • Cloudflare R2

    your evidence bucket

Does your app qualify?

Browser
Chromium, driven by Playwright
Intake
one email mailbox — Gmail or Outlook
Environment
staging — production refused unless you override it
Not yet
Firefox, Safari / WebKit, and native mobile
428
tests on our own product · Aug 2026
80%
of our code covered · Aug 2026
real Chromium
not a simulation
read-only
on your code

What it costs

You pay for tests that stay.

One unit: a test that is still in the suite, still catching regressions. The part you actually keep.

  • Per test kept in the suite
  • Not per seat
  • Not per bug we look at
  • Not per run

A test only counts once it has survived a real failure and been activated by a person.

Book a demo

Send us the last bug that reached a customer. We will show you the test that catches it.

never writes to your code·staging unless you override it