Quality assurance for the AI era

Finds it. Fixes it.
Proves it.

It reads the code you have already shipped and finds the bugs and security holes nobody has reported yet. Then it proves the fix with a test that fails before the change and passes after.

What it does
Hunts defects nobody reported.
What comes back
The fix, and the run that proves it.
What it touches
Nothing you did not approve.
  1. SIGNAL
  2. INVESTIGATE
  3. REPRODUCE
  4. DIAGNOSE
  5. REPORT
  6. PATCH
  7. TEST
  8. VERIFY
  9. REVIEW

Credda proposes the diff. A person merges it.

01Find

1229 defects across 751 packages, 1192 with no prior report.

Found by reading 25,177 published packages across 3 sweeps, with no bug report in hand. Each ran at the commit beside it, and again at the maintainer’s fix.

  • @sentry/core
  • lightningcss
  • napi-postinstall
  • tinypool
  • prisma
  • @vitest/utils
  • string.prototype.repeat
  • @babel/helper-validator-identifier
  • miniflare
  • @babel/types
  • terser
  • import-meta-resolve
  • vite-node
  • semver
  • node-fetch
  • js-yaml
  • is-my-json-valid
  • arraybuffer.prototype.slice
  • aria-query
  • dunder-proto
  • electron-to-chromium
  • merge
  • fast-xml-parser
  • ramda
  • dotenv
  • traverse
  • node-persist
  • getopts
  • bytes
  • diacritics
  • figlet
  • simple-get
  • streamx
  • readdir-glob
  • typed-array-byte-length
  • filename-reserved-regex
  • superagent
  • make-fetch-happen
  • tapable
  • logform
  • minipass-fetch
  • popsicle-redirects
  • fast-deep-merge
  • gaxios
  • isomorphic-fetch
  • @remix-run/web-fetch
  • electron-fetch
  • node-fetch-commonjs
  • download
  • object-path-immutable
  • @standard-schema/spec
  • property-expr
  • minipass-sized
  • signal-exit
  • filenamify
  • yargs
  • mongoose
  • cssfilter
  • websocket-extensions
  • rate-limiter-flexible
  • mongodb
  • bson
  • csv-generate
  • mailgun.js
  • express-validator
  • mysql2
  • serialize-javascript
  • terser-webpack-plugin
  • minimizer-webpack-plugin
  • nx
  • postcss-normalize-url
  • tsx
  • @vue/compiler-sfc
  • source-map
  • get-uri
  • probe-image-size
  • npm-registry-fetch
  • pacote
  • @nx/devkit
  • @octokit/plugin-paginate-rest
  • @babel/plugin-syntax-import-attributes
  • reghex
  • is-npm
  • prettier
  • protobufjs
  • i18next
  • rambda
  • suffix-thumb
  • libsodium-wrappers
  • chrono-node
  • compromise
  • fuse.js
  • @firebase/database
  • @azure/msal-browser
  • @cypress/request-promise
  • popsicle
  • request-light
  • openid-client
  • property-information
  • sisteransi
  • cli-tableau
  • exceljs
  • pm2
  • xlsx
  • postcss-minify-selectors
  • react-router
  • preact
  • @lit/reactive-element
  • recoil
  • @vue/runtime-core
  • @parcel/runtime-rsc
  • expect
  • @whatwg-node/node-fetch
  • apollo-server-env
  • eslint-scope
  • @apollo/protobufjs
  • weak-lru-cache
  • @prisma/query-plan-executor
  • ethereum-cryptography
  • formdata-node
  • cbor-x
  • @octokit/auth-unauthenticated
  • ethers
  • @google-cloud/functions-framework
  • sharp
  • @fastify/swagger

The 169 with a disclosure record, and every sweep behind the rest

02Reproduce

158 bug reports we did not write. 110 reproduced.

Closed issues from 60 repositories, pinned where the bug was present, unedited. That is the scored slice of a reproduce corpus now holding 357 admitted cases in JavaScript, Python and Elixir — every corpus, and what each one measured.

  • Right failure reproduced

    110 of 158 · 70%

    cases scored, of 158 admitted with the defect present

    LIVE, bench/external/scorecard.json, 2026-09-20

  • False successes

    0

    claims of no change required, holding the captured failure

    LIVE and RECORDED, every graded run

  • Reproduced, cases we wrote

    10 of 10 · 100%

    seeded cases with a failure to reproduce

    bench/scorecard.json, 2026-08-29

  • Reproduced, six languages

    63 of 63

    placed defects across JavaScript, Python, Go, Rust, Ruby and Java, reproduced with no model

    bench/language-reproduction/scorecard.json, 2026-09-18

LIVE verdictsbench/external/scorecard.json
2026-09-20 · 158 checkouts in 18408.5 s · 5 errored. Every chip links to its run.

03Record

What one run produced.

The queue, the run against the unfixed tree, and throw separated from fault.

Triage what arrived

13 seeded runs, ordered by what finishes first.

console · what needs a personbench/scorecard.json · 2026-08-29

Membership and order come from attentionReason() and attentionRank(), the two functions the console files its own queue with, rather than a second copy of them written for this page. 1 of 13 runs leave something for a person. Nothing here is live, and this instance has no customers and no runs of its own.

The console's queue, one row per committed case, with the outcome recorded for it and what it leaves for a person.
CaseOutcome recordedWaiting on a person
vague-performance-reportNo runnable checkSharpen the report. Nothing ran: no runnable check could be derived from the report. Nothing was established about this repository in either direction.
async-unhandled-rejectionVerifiedNothing waiting
auth-idor-order-lookupVerifiedNothing waiting
checkout-tax-missing-countryVerifiedNothing waiting
command-injection-log-searchVerifiedNothing waiting
config-not-codeNo change requiredNothing waiting
issue-already-resolvedNo change requiredNothing waiting
pagination-off-by-oneVerifiedNothing waiting
path-traversal-attachment-downloadVerifiedNothing waiting
regression-from-recent-changeVerifiedNothing waiting
symptom-vs-cause-trapVerifiedNothing waiting
vulnerability-not-exploitableNo change requiredNothing waiting
working-as-intendedReproduced; the tests assert itNothing waiting

Reproduce before explaining

Against the tree with the defect still in it.

repro-268.js · unpatched treenode v24.18.0 · vitest 2.1.9
$ node repro-268.js

src/stock-api.js:28
  const available = record.onHand - record.reserved;
                           ^

TypeError: Cannot read properties of undefined (reading 'onHand')
    at availabilityFor (src/stock-api.js:28:28)
    at Object.<anonymous> (repro-268.js:9:13)

exit code 1

Separate throw from fault

Where it threw, and where it went wrong.

src/stock-api.js · where it threw
src/stock-api.js:27

function availabilityFor(store, sku) {
  const record = store.lookup(sku);
  const available = record.onHand - record.reserved;
src/stock-store.js · lookup()
src/stock-store.js:20  (createStockStore)

  const key = normalizeSku(row.sku);      // every key is normalised
  index.set(key, { sku: key, onHand: ... });

src/stock-store.js:41  (lookup)

  return index.get(sku);                  // this one is not

bench/scorecard.json 2026-08-29 · case symptom-vs-cause-trap 2026-08-22, node v24.18.0 · vitest 2.1.9. Our own work.

04Report

What a report contains.

Each stage, with the record it produced. When the fix is proven, the last one is a pull request you review and merge.

SIGNAL

camelcase#46 · as filedcommit 24d711f

preserveCamelCase malfunctions on "A::a"

    > const camelcase = require("camelcase");
    undefined
    > camelcase("A::a");
    "a:-:a"
    > camelcase("A::a",{pascalCase:true});
    "A:-:a"

I'm not saying this would be common in the wild, but this is nonetheless a surprising behavior.

Note that `c.toLowerCase() === c` and `c.toUpperCase() === c` both evaluates to true when c does not contain any alphabets.
Issue
#46
Commit
24d711f77ca11fda56aec7ef899ea16c73246f6e
Why this commit
The fix commit's parent where the closing commit was identifiable in the repository, otherwise the commit that was HEAD of the default branch at the moment the issue was filed. fixCommit bound 2026-08-26: issue #46 was closed by its own reporter as a duplicate of #42 ('Duplicate of #42', the only comment on the thread), and #42 was fixed by PR #49, squash-merged as bba938e. That commit changes exactly the two lines the reporter diagnosed -- isLastCharLower/isLastCharUpper in preserveCamelCase now also require the character to HAVE an opposite-case variant -- and its test.js hunk adds `camelCase('A::a') === 'a::a'` and `camelCase('A::a', {pascalCase: true}) === 'A::a'`, the reporter's own two expressions. It is not this case's pinned parent (the pin is HEAD-at-filing), so the two are not two ends of one edge here.
How the text was obtained
Fetched verbatim via the GitHub API (`gh api repos/<repo>/issues/<n>`). Title on the first line, body unmodified below it. Nothing was paraphrased, cleaned up, or supplemented.
Toolchain
javascript · node · ava · npm

REPRODUCE

camelcase#46 · reproduction attemptLIVE · RIGHT_FAILURE
Checks in this reproduction attempt.
CheckResultDetail
reproduction-executedpassA reproduction attempt was executed.
signature-capturedpass`camelcase("A::a")` still produces "a:-:a" (read a:-:a)
right-failurepassReproduced the reported failure: camelcase('A::a') returns 'a:-:a' instead of leaving the non-alphabetic separator alone.
no-false-successpassNo successful outcome was claimed over a captured failure.
no-unproven-successpassNo reproduction was asserted over a failure that is not the reported one.

provenance changes here seeded case symptom-vs-cause-trap, 2026-08-22. No external run reached diagnosis.

REPORT

Evidence ledger5 records

The trail for issue 268, executed 2026-08-22.

The evidence ledger, one row per record, with its type, phase, strength and summary.
IDTypePhaseStrengthSummary
ev-01ReproductionbeforeStrongTypeError: Cannot read properties of undefined (reading 'onHand'), exit 1
ev-02Stack TracebeforeStrongOrigin frame inside the repository: src/stock-api.js:28 in availabilityFor
ev-03Code ReferenceindependentModerateIndex keys are written through normalizeSku(); lookup() reads index.get(sku) raw
ev-04Test ResultbeforeStrongRegression test for issue 268: 2 failed against the unpatched tree
ev-05Test ResultafterStrongPatched tree: regression 2 / 2 and the existing suite 12 / 12

REVIEW

3 scopes, one repository write. contents: write is not among them, and a committed test fails if a merge call appears in any connection-layer package, last captured 2026-08-22. The whole grant.

8 of 8 cases expecting a change produced one. 0 of 13 changed what nothing asked for. packages/shared/src/states.ts · ADR 0018, ADR 0019

05Ledger

A rate means nothing if the misses are hidden.

What the reporter described, beside what Credda captured.

camelcase#46 · commit 24d711ftwo runs, one case
SIGNAL
> const camelcase = require("camelcase");
undefined
> camelcase("A::a");
"a:-:a"
The report, unedited. Issue 46.
REPORTED
camelcase("A::a") → "a:-:a"
What the reporter said should be reproduced.
OBSERVED
SyntaxError: Unexpected token '>'
WRONG_FAILUREA real failure, and the wrong one: the run executed the REPL transcript as a script and tripped over its own prompt characters.
OBSERVED2026-09-20
`camelcase("A::a")` still produces "a:-:a" (read a:-:a)
RIGHT_FAILUREThe same case, executed against the upstream checkout today. This is the reported defect, not a failure that resembles it.

NO_CHANGE_REQUIRED ran and found nothing; NO_RUNNABLE_CHECK ran nothing. Separate metrics.

bench/scorecard.json 2026-08-29 5 of 5 abstention cases reached the expected outcome. Every miss, separately.

06Next

The next environment is a machine, and it is simulated.

An autonomous system states what its action is expected to cause before it acts, and evidence settles the claim afterwards. One loop either way: observe, understand, plan, act, verify, learn.

in developmentA domain-neutral platform and a deterministic manufacturing cell. Versioned contracts, a hash-chained event log, six autonomy levels with a human approval step, and verification that judges the expectations stated before an action from sealed events. In one recorded run, reducing the load on the failing machine was forecast to produce 44 good units against 50 for doing nothing, and the run reports that rather than hiding it behind a ranking.

simulatedNo robot, PLC, MES, sensor, camera or plant is connected. No model has been trained, there is no pilot and no customer, and none of it is for sale. Every figure from that run carries the word SIMULATED.

Install

Two things you paste.

A GitHub Action, in your own runner, on your own token. Or the app, on ours.

The workflowyaml
# .github/workflows/credda.yml
name: Credda on labeled issues

on:
  issues:
    types: [labeled]

permissions:
  contents: read   # checkout of the repository under test
  issues: write    # the one report comment
  id-token: write  # mint the OIDC token that fetches the engine

jobs:
  investigate:
    if: github.event.label.name == 'credda'
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - uses: Credda-io/action@v1
        with:
          label: credda
          # license: ${{ secrets.CREDDA_LICENSE }}
        # with:
        #   anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
Create the trigger labelgh, once
gh label create credda --description 'Credda reproduces this bug in a sandbox and comments what it established.'

permissions: is the whole grant. Pin the tag. The commentary, and the triage job.

the other way inThe app is one click and runs on every push, but clones onto Credda’s infrastructure rather than into your runner. Both paths, side by side.

Point it at a repository you already trust.

It comes back with the failure, or with nothing.