tewip-ai 0.70.17 → 0.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QUICKSTART.md +178 -178
- package/README.md +54 -5
- package/dist/cli/help.js +268 -239
- package/dist/cli/tewip.js +49 -15
- package/dist/cli/verbs-assure.js +54 -0
- package/dist/engine/access/access-command.js +8 -3
- package/dist/engine/attest/attest.js +37 -2
- package/dist/engine/audit/audit-command.js +53 -0
- package/dist/engine/audit/audit.js +109 -0
- package/dist/engine/autofix/autofix.js +24 -10
- package/dist/engine/autofix/code-propose.js +8 -8
- package/dist/engine/autofix/fix-data.js +25 -17
- package/dist/engine/autofix/fix-wait.js +27 -18
- package/dist/engine/build/build-command.js +1 -1
- package/dist/engine/build/build.js +22 -22
- package/dist/engine/iac/compose.js +74 -0
- package/dist/engine/iac/dockerfile.js +79 -0
- package/dist/engine/iac/iac-command.js +132 -0
- package/dist/engine/incident/incident.js +41 -3
- package/dist/engine/learn/learn-command.js +8 -1
- package/dist/engine/llm/prompt.js +22 -22
- package/dist/engine/llm/usage.js +13 -3
- package/dist/engine/notify/note-command.js +6 -2
- package/dist/engine/portfolio/portfolio-command.js +144 -0
- package/dist/engine/portfolio/portfolio.js +54 -0
- package/dist/engine/prove/changed.js +50 -2
- package/dist/engine/prove/prove.js +9 -2
- package/dist/engine/recall/recall.js +55 -12
- package/dist/engine/recall/same.js +116 -0
- package/dist/engine/release/channels.js +36 -6
- package/dist/engine/safety/safety-command.js +97 -0
- package/dist/engine/safety/safety.js +93 -0
- package/dist/engine/sbom/inventory.js +179 -0
- package/dist/engine/sbom/licences.js +77 -0
- package/dist/engine/sbom/sbom-command.js +127 -0
- package/dist/engine/schema/migration-files.js +25 -0
- package/dist/engine/secure/jwt.js +47 -0
- package/dist/engine/secure/secrets.js +8 -42
- package/dist/engine/secure/secure-command.js +37 -5
- package/dist/engine/secure/triage.js +50 -1
- package/dist/engine/taint/flow.js +111 -0
- package/dist/engine/verdict/verdict-command.js +9 -2
- package/dist/engine/verdict/verdict.js +11 -2
- package/dist/engine/vouch/assertions.js +80 -2
- package/dist/engine/vouch/text.js +25 -0
- package/dist/engine/vouch/vouch.js +23 -2
- package/dist/engine/walk.js +67 -0
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/tools-prove.js +14 -0
- package/dist/outlets/items.js +11 -1
- package/package.json +4 -1
package/QUICKSTART.md
CHANGED
|
@@ -1,179 +1,179 @@
|
|
|
1
|
-
# Quickstart: putting Tewip on one repository
|
|
2
|
-
|
|
3
|
-
For an engineer adding the agent to a project that already runs Playwright tests in GitHub Actions. It takes about ten minutes, and the first useful output arrives with the next failing run.
|
|
4
|
-
|
|
5
|
-
Start with **one** repository whose tests fail sometimes. A repository whose suite is always green has nothing to triage.
|
|
6
|
-
|
|
7
|
-
## What the agent does once it is installed
|
|
8
|
-
|
|
9
|
-
Every CI run, for every failed test, it decides the root cause — application bug, changed selector, race, environment, or test data — with a confidence, the evidence it used, and one concrete next action. It then delivers that to the people who need it: a comment on the pull request, the board in the job summary, one grouped issue for environment failures, and optionally a separate pull request with locator fixes that it re-ran and verified.
|
|
10
|
-
|
|
11
|
-
It never merges anything, never edits application code, and never opens a fix pull request for a change it has not proved by re-running the test.
|
|
12
|
-
|
|
13
|
-
## Step 1: make Playwright leave the evidence behind
|
|
14
|
-
|
|
15
|
-
The agent reads Playwright's own blob report and traces, so nothing from this project goes into your test config:
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
// playwright.config.ts
|
|
19
|
-
reporter: process.env.CI ? [['list'], ['blob']] : 'list',
|
|
20
|
-
use: { trace: 'retain-on-failure' },
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
If your config already uses a reporter list in CI, add `['blob']` to it.
|
|
24
|
-
|
|
25
|
-
## Step 2: add one step to the workflow that runs the tests
|
|
26
|
-
|
|
27
|
-
```yaml
|
|
28
|
-
permissions:
|
|
29
|
-
pull-requests: write # the diagnosis comment
|
|
1
|
+
# Quickstart: putting Tewip on one repository
|
|
2
|
+
|
|
3
|
+
For an engineer adding the agent to a project that already runs Playwright tests in GitHub Actions. It takes about ten minutes, and the first useful output arrives with the next failing run.
|
|
4
|
+
|
|
5
|
+
Start with **one** repository whose tests fail sometimes. A repository whose suite is always green has nothing to triage.
|
|
6
|
+
|
|
7
|
+
## What the agent does once it is installed
|
|
8
|
+
|
|
9
|
+
Every CI run, for every failed test, it decides the root cause — application bug, changed selector, race, environment, or test data — with a confidence, the evidence it used, and one concrete next action. It then delivers that to the people who need it: a comment on the pull request, the board in the job summary, one grouped issue for environment failures, and optionally a separate pull request with locator fixes that it re-ran and verified.
|
|
10
|
+
|
|
11
|
+
It never merges anything, never edits application code, and never opens a fix pull request for a change it has not proved by re-running the test.
|
|
12
|
+
|
|
13
|
+
## Step 1: make Playwright leave the evidence behind
|
|
14
|
+
|
|
15
|
+
The agent reads Playwright's own blob report and traces, so nothing from this project goes into your test config:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// playwright.config.ts
|
|
19
|
+
reporter: process.env.CI ? [['list'], ['blob']] : 'list',
|
|
20
|
+
use: { trace: 'retain-on-failure' },
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If your config already uses a reporter list in CI, add `['blob']` to it.
|
|
24
|
+
|
|
25
|
+
## Step 2: add one step to the workflow that runs the tests
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
permissions:
|
|
29
|
+
pull-requests: write # the diagnosis comment
|
|
30
30
|
issues: write
|
|
31
|
-
actions: read # so it can read a failed job's log when no report was written # the grouped environment issue
|
|
32
|
-
contents: write # only if you turn autofix on
|
|
33
|
-
|
|
34
|
-
steps:
|
|
35
|
-
# ... your existing checkout, install, and `npx playwright test` steps ...
|
|
36
|
-
|
|
37
|
-
- name: Tewip
|
|
38
|
-
if: always() # it must run even though the test step failed
|
|
39
|
-
uses: hmamut39/tewip@main
|
|
40
|
-
with:
|
|
41
|
-
openai-api-key: ${{ secrets.OPENAI_API_KEY }} # optional, see step 3
|
|
42
|
-
autofix: 'false' # start with this off
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
`if: always()` matters: without it the step is skipped exactly when there is something to triage.
|
|
46
|
-
|
|
47
|
-
Keep `autofix: 'false'` for the first week. Read what the agent says, decide whether you trust it, and turn fixing on afterwards.
|
|
48
|
-
|
|
49
|
-
## Step 3: decide whether to give it an API key
|
|
50
|
-
|
|
51
|
-
| Without a key | With `OPENAI_API_KEY` |
|
|
52
|
-
|---|---|
|
|
53
|
-
| Only the deterministic rules run | The rules run first, and only what they cannot settle goes to the model |
|
|
54
|
-
| Every answer is explainable from the error, the trace and the test's history | Adds a judgement on the rest, with its reasoning and evidence shown |
|
|
55
|
-
| Free | A few cents per run in practice, because the rules answer most failures |
|
|
56
|
-
|
|
57
|
-
On real projects the rules alone decide most failures and are right on 96–98% of what they decide, so starting without a key is a reasonable first week. To add one later: repository **Settings → Secrets and variables → Actions → New repository secret**, named `OPENAI_API_KEY`.
|
|
58
|
-
|
|
59
|
-
Every run prints what it cost, priced from OpenAI's published prices. One guard worth setting once the key is in place:
|
|
60
|
-
|
|
61
|
-
```yaml
|
|
62
|
-
env:
|
|
63
|
-
TRIAGE_LLM_MAX_CALLS: '80' # hard cap on model calls per run
|
|
64
|
-
# TRIAGE_LLM_PRICE_IN / _OUT: only if your price differs (per million tokens)
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Not using Playwright? Every stack works
|
|
68
|
-
|
|
69
|
-
Point the agent at your test runner's **JUnit XML** report (or .NET's **TRX**) instead of a Playwright blob report. Each runner marked *verified* was run for real in CI (`fixtures/polyglot`) and its report is checked by the test suite on every change.
|
|
70
|
-
|
|
71
|
-
| Stack | Runner | How to write the report | Status |
|
|
72
|
-
|---|---|---|---|
|
|
73
|
-
| **Node.js** | node:test (built in) | `node --test --test-reporter=junit --test-reporter-destination=report.xml` | verified |
|
|
74
|
-
| Node.js, React, Vue, Angular, Next.js, NestJS, Express | Jest | `jest --reporters=default --reporters=jest-junit` | verified |
|
|
75
|
-
| Vite, Vue, Svelte, Nuxt, React | Vitest | `vitest run --reporter=junit --outputFile=report.xml` | verified |
|
|
76
|
-
| Node.js, Express | Mocha | `mocha --reporter mocha-junit-reporter` | verified |
|
|
77
|
-
| **Python**, Django, Flask, FastAPI | pytest (also runs `unittest`) | `pytest --junitxml=report.xml` (retries: `pytest-rerunfailures`) | verified |
|
|
78
|
-
| **Java**, Spring, Kotlin | JUnit 4/5, TestNG via Maven Surefire | written by default to `target/surefire-reports/` (retries: `rerunFailingTestsCount`) | verified |
|
|
79
|
-
| Java, Kotlin, Android | Gradle | written by default to `build/test-results/test/` | same format as Surefire |
|
|
80
|
-
| **Go** | gotestsum | `gotestsum --junitfile report.xml` | verified |
|
|
81
|
-
| **.NET** (C#, F#), ASP.NET | xUnit, NUnit, MSTest | `dotnet test --logger trx` (native) or `--logger junit` | both verified |
|
|
82
|
-
| **Ruby**, Rails | RSpec | `rspec --format RspecJunitFormatter --out report.xml` | verified |
|
|
83
|
-
| **PHP**, Laravel, Symfony | PHPUnit | `phpunit --log-junit report.xml` | verified |
|
|
84
|
-
| **Rust** | cargo-nextest | `[profile.ci.junit]` in `.config/nextest.toml` | verified |
|
|
85
|
-
| End-to-end | **Selenium** (Java, Python, JavaScript, C#) | through the runner above it: Surefire, pytest, Jest/Mocha, `dotnet test` | JUnit format; error wording read |
|
|
86
|
-
| End-to-end | Cypress, WebdriverIO | `mocha-junit-reporter` / `@wdio/junit-reporter` | JUnit format; error wording read |
|
|
87
|
-
| End-to-end | **Playwright** | blob reporter (step 1) — adds traces, selector drift and verified fixes | verified on 5 real projects |
|
|
88
|
-
|
|
89
|
-
```yaml
|
|
90
|
-
- name: Tewip
|
|
91
|
-
if: always()
|
|
92
|
-
uses: hmamut39/tewip@main
|
|
93
|
-
with:
|
|
94
|
-
junit-report: report.xml # a file, or a directory of them (.xml and .trx)
|
|
95
|
-
suite: unit # only needed when one workflow triages several suites
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
What it reads from any of these: the failure text, retries, and each test's history. From that it tells apart a wrong value (a real bug once the test has a passing history), an unreachable service (environment), a data collision, and a test that failed then passed on a retry (timing), in the wording each language uses: `expected: <4> but was: <3>` in Java, `got 3, want 4` in Go, `AssertionError: 3 != 4` in Python, `Expected: 4 / Actual: 3` in .NET, and so on. It also reads each browser tool's own words for the same three problems: an element that was never found (Selenium's `NoSuchElementException`, WebdriverIO's `still not displayed`, Cypress's `Expected to find element`), a click another element received (Selenium's `Other element would receive the click`, Cypress's `is being covered by another element`), and an element the page replaced mid-test (Selenium's `StaleElementReferenceException`, Cypress's `the page updated while this command was executing`). No labelled Selenium or Cypress runs have measured those rules yet, so they report at a confidence the merge gate does not trust on its own. What it cannot do without Playwright's traces is look at the page, so selector drift and automatic fixes stay Playwright-only.
|
|
99
|
-
|
|
100
|
-
A wrong value on a test's **first** recorded failure stays undecided rather than guessed: one failure alone does not show whether the test was reliable before. It becomes a real-bug diagnosis once the test's history shows it passing and then failing the same way.
|
|
101
|
-
|
|
102
|
-
When one workflow triages several suites (say `unit` and `e2e`), give each a `suite` name: each then keeps its own history and its own comment, and corrections name the suite, as in `/triage TIMING unit#2 flaky on CI`.
|
|
103
|
-
|
|
104
|
-
## On your own machine, without CI
|
|
105
|
-
|
|
106
|
-
Install the command once from the release file, `npm install -g tewip-<version>.tgz` (Tewip is not on the npm registry yet; Node 22.18 or newer), run your tests with the report switched on (see the table above), then:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
tewip explain report.xml # JUnit XML or .trx
|
|
110
|
-
tewip explain reports/ # a folder of them
|
|
111
|
-
tewip explain blob-report/ # Playwright
|
|
112
|
-
tewip ci owner/repo --pr 12 # what Tewip's GitHub Action said about a pull request
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
It prints the same triage board CI writes: each failure's cause, confidence, evidence and next action. Each run is kept in a `.tewip/` folder in your project (add it to `.gitignore`), so from the second run on, failures are judged against their history exactly as in CI. `--name` keeps separate histories for different projects.
|
|
116
|
-
|
|
117
|
-
## What you will see on the next failing run
|
|
118
|
-
|
|
119
|
-
- **On the pull request:** one comment listing each failing test, grouped by whether your change likely caused it, each with a cause, a confidence, the evidence and the next action. It updates in place rather than adding a comment per run.
|
|
120
|
-
- **In the job summary:** the same failures as a triage board.
|
|
121
|
-
- **As an issue:** environment failures (5xx responses, connection resets, outages) grouped into one issue instead of one per test.
|
|
122
|
-
- **As an artifact** named `tewip-report`: every role's view, including the engineering-quality view with the flaky tests ranked by the CI minutes they cost.
|
|
123
|
-
|
|
124
|
-
## Correcting it
|
|
125
|
-
|
|
126
|
-
When it gets one wrong, reply to its comment:
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
/triage TIMING #2 this one is flaky on our CI runners, not a bug
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
From the next run on, that failure of that test gets your answer, shown as "corrected by a person" with your name and reason. A correction settles the cause; it never makes the agent change code.
|
|
133
|
-
|
|
134
|
-
## Asking it questions from your editor
|
|
135
|
-
|
|
136
|
-
- **VS Code, Cursor, Windsurf, VSCodium:** install the Tewip extension (*Extensions → … → Install from VSIX*, `tewip-<version>.vsix`). It connects Tewip to the editor's AI assistant by itself and adds *Tewip: Explain a test report…* and *Tewip: Why did CI fail on this branch?*
|
|
137
|
-
- **JetBrains (2025.2+), Claude, and other MCP clients:** add one server whose command is `tewip mcp`.
|
|
138
|
-
|
|
139
|
-
Then ask, in plain language: "why did CI fail on my PR?", "which tests are flaky in checkout?", "is main safe to release?". Every tool is read-only, and it reads the report the Action already uploaded, so you do not need the other repository cloned.
|
|
140
|
-
|
|
141
|
-
## Stop flaky tests from blocking merges (optional)
|
|
142
|
-
|
|
143
|
-
Once you trust its answers, let the agent decide whether a failed run should block:
|
|
144
|
-
|
|
145
|
-
```yaml
|
|
146
|
-
- name: Tests
|
|
147
|
-
continue-on-error: true # the gate below decides
|
|
148
|
-
run: npx playwright test
|
|
149
|
-
- name: Tewip
|
|
150
|
-
if: always()
|
|
151
|
-
uses: hmamut39/tewip@main
|
|
152
|
-
with:
|
|
153
|
-
gate: real-failures
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
The build then fails only for real bugs, changed selectors, test-data problems and anything undecided. Failures a rule or a person classified as flaky or environment no longer block. On 2,296 real failures this unblocked 84% of the flaky and environment ones without letting a real bug through.
|
|
157
|
-
|
|
158
|
-
## Turning fixing on, once you trust it
|
|
159
|
-
|
|
160
|
-
```yaml
|
|
161
|
-
autofix: 'true'
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
It then rewrites a drifted locator, re-runs that single test, and opens a **separate** pull request only with the changes that passed. Review it like any other pull request: an intended UI change and a regression can look identical from the outside, which is exactly why a human merges it.
|
|
165
|
-
|
|
166
|
-
On real WordPress CI data it would have fixed 14 drifted locators with none wrong, and every locator it suggested matched what the developers themselves wrote.
|
|
167
|
-
|
|
168
|
-
## If something does not appear
|
|
169
|
-
|
|
170
|
-
| Symptom | Cause |
|
|
171
|
-
|---|---|
|
|
172
|
-
| The step ran but says "no blob report" | The blob reporter is not on in CI, or the tests step did not run |
|
|
173
|
-
| No comment on the pull request | The run was not triggered by a pull request, or `pull-requests: write` is missing |
|
|
174
|
-
| "Resource not accessible by integration" | The workflow's permissions block is missing an entry |
|
|
175
|
-
| Diagnoses look thin on the first day | The agent judges each failure against that test's history, which it builds from your runs; it gets better as runs accumulate |
|
|
176
|
-
|
|
177
|
-
## What it costs, and what it keeps
|
|
178
|
-
|
|
179
|
-
The agent stores the run history in the Actions cache, never in your repository. Collected failure data and traces stay in CI. The only thing it writes to your repository is a pull request branch, and only when you turn fixing on.
|
|
31
|
+
actions: read # so it can read a failed job's log when no report was written # the grouped environment issue
|
|
32
|
+
contents: write # only if you turn autofix on
|
|
33
|
+
|
|
34
|
+
steps:
|
|
35
|
+
# ... your existing checkout, install, and `npx playwright test` steps ...
|
|
36
|
+
|
|
37
|
+
- name: Tewip
|
|
38
|
+
if: always() # it must run even though the test step failed
|
|
39
|
+
uses: hmamut39/tewip@main
|
|
40
|
+
with:
|
|
41
|
+
openai-api-key: ${{ secrets.OPENAI_API_KEY }} # optional, see step 3
|
|
42
|
+
autofix: 'false' # start with this off
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`if: always()` matters: without it the step is skipped exactly when there is something to triage.
|
|
46
|
+
|
|
47
|
+
Keep `autofix: 'false'` for the first week. Read what the agent says, decide whether you trust it, and turn fixing on afterwards.
|
|
48
|
+
|
|
49
|
+
## Step 3: decide whether to give it an API key
|
|
50
|
+
|
|
51
|
+
| Without a key | With `OPENAI_API_KEY` |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Only the deterministic rules run | The rules run first, and only what they cannot settle goes to the model |
|
|
54
|
+
| Every answer is explainable from the error, the trace and the test's history | Adds a judgement on the rest, with its reasoning and evidence shown |
|
|
55
|
+
| Free | A few cents per run in practice, because the rules answer most failures |
|
|
56
|
+
|
|
57
|
+
On real projects the rules alone decide most failures and are right on 96–98% of what they decide, so starting without a key is a reasonable first week. To add one later: repository **Settings → Secrets and variables → Actions → New repository secret**, named `OPENAI_API_KEY`.
|
|
58
|
+
|
|
59
|
+
Every run prints what it cost, priced from OpenAI's published prices. One guard worth setting once the key is in place:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
env:
|
|
63
|
+
TRIAGE_LLM_MAX_CALLS: '80' # hard cap on model calls per run
|
|
64
|
+
# TRIAGE_LLM_PRICE_IN / _OUT: only if your price differs (per million tokens)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Not using Playwright? Every stack works
|
|
68
|
+
|
|
69
|
+
Point the agent at your test runner's **JUnit XML** report (or .NET's **TRX**) instead of a Playwright blob report. Each runner marked *verified* was run for real in CI (`fixtures/polyglot`) and its report is checked by the test suite on every change.
|
|
70
|
+
|
|
71
|
+
| Stack | Runner | How to write the report | Status |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| **Node.js** | node:test (built in) | `node --test --test-reporter=junit --test-reporter-destination=report.xml` | verified |
|
|
74
|
+
| Node.js, React, Vue, Angular, Next.js, NestJS, Express | Jest | `jest --reporters=default --reporters=jest-junit` | verified |
|
|
75
|
+
| Vite, Vue, Svelte, Nuxt, React | Vitest | `vitest run --reporter=junit --outputFile=report.xml` | verified |
|
|
76
|
+
| Node.js, Express | Mocha | `mocha --reporter mocha-junit-reporter` | verified |
|
|
77
|
+
| **Python**, Django, Flask, FastAPI | pytest (also runs `unittest`) | `pytest --junitxml=report.xml` (retries: `pytest-rerunfailures`) | verified |
|
|
78
|
+
| **Java**, Spring, Kotlin | JUnit 4/5, TestNG via Maven Surefire | written by default to `target/surefire-reports/` (retries: `rerunFailingTestsCount`) | verified |
|
|
79
|
+
| Java, Kotlin, Android | Gradle | written by default to `build/test-results/test/` | same format as Surefire |
|
|
80
|
+
| **Go** | gotestsum | `gotestsum --junitfile report.xml` | verified |
|
|
81
|
+
| **.NET** (C#, F#), ASP.NET | xUnit, NUnit, MSTest | `dotnet test --logger trx` (native) or `--logger junit` | both verified |
|
|
82
|
+
| **Ruby**, Rails | RSpec | `rspec --format RspecJunitFormatter --out report.xml` | verified |
|
|
83
|
+
| **PHP**, Laravel, Symfony | PHPUnit | `phpunit --log-junit report.xml` | verified |
|
|
84
|
+
| **Rust** | cargo-nextest | `[profile.ci.junit]` in `.config/nextest.toml` | verified |
|
|
85
|
+
| End-to-end | **Selenium** (Java, Python, JavaScript, C#) | through the runner above it: Surefire, pytest, Jest/Mocha, `dotnet test` | JUnit format; error wording read |
|
|
86
|
+
| End-to-end | Cypress, WebdriverIO | `mocha-junit-reporter` / `@wdio/junit-reporter` | JUnit format; error wording read |
|
|
87
|
+
| End-to-end | **Playwright** | blob reporter (step 1) — adds traces, selector drift and verified fixes | verified on 5 real projects |
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
- name: Tewip
|
|
91
|
+
if: always()
|
|
92
|
+
uses: hmamut39/tewip@main
|
|
93
|
+
with:
|
|
94
|
+
junit-report: report.xml # a file, or a directory of them (.xml and .trx)
|
|
95
|
+
suite: unit # only needed when one workflow triages several suites
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
What it reads from any of these: the failure text, retries, and each test's history. From that it tells apart a wrong value (a real bug once the test has a passing history), an unreachable service (environment), a data collision, and a test that failed then passed on a retry (timing), in the wording each language uses: `expected: <4> but was: <3>` in Java, `got 3, want 4` in Go, `AssertionError: 3 != 4` in Python, `Expected: 4 / Actual: 3` in .NET, and so on. It also reads each browser tool's own words for the same three problems: an element that was never found (Selenium's `NoSuchElementException`, WebdriverIO's `still not displayed`, Cypress's `Expected to find element`), a click another element received (Selenium's `Other element would receive the click`, Cypress's `is being covered by another element`), and an element the page replaced mid-test (Selenium's `StaleElementReferenceException`, Cypress's `the page updated while this command was executing`). No labelled Selenium or Cypress runs have measured those rules yet, so they report at a confidence the merge gate does not trust on its own. What it cannot do without Playwright's traces is look at the page, so selector drift and automatic fixes stay Playwright-only.
|
|
99
|
+
|
|
100
|
+
A wrong value on a test's **first** recorded failure stays undecided rather than guessed: one failure alone does not show whether the test was reliable before. It becomes a real-bug diagnosis once the test's history shows it passing and then failing the same way.
|
|
101
|
+
|
|
102
|
+
When one workflow triages several suites (say `unit` and `e2e`), give each a `suite` name: each then keeps its own history and its own comment, and corrections name the suite, as in `/triage TIMING unit#2 flaky on CI`.
|
|
103
|
+
|
|
104
|
+
## On your own machine, without CI
|
|
105
|
+
|
|
106
|
+
Install the command once from the release file, `npm install -g tewip-<version>.tgz` (Tewip is not on the npm registry yet; Node 22.18 or newer), run your tests with the report switched on (see the table above), then:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
tewip explain report.xml # JUnit XML or .trx
|
|
110
|
+
tewip explain reports/ # a folder of them
|
|
111
|
+
tewip explain blob-report/ # Playwright
|
|
112
|
+
tewip ci owner/repo --pr 12 # what Tewip's GitHub Action said about a pull request
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
It prints the same triage board CI writes: each failure's cause, confidence, evidence and next action. Each run is kept in a `.tewip/` folder in your project (add it to `.gitignore`), so from the second run on, failures are judged against their history exactly as in CI. `--name` keeps separate histories for different projects.
|
|
116
|
+
|
|
117
|
+
## What you will see on the next failing run
|
|
118
|
+
|
|
119
|
+
- **On the pull request:** one comment listing each failing test, grouped by whether your change likely caused it, each with a cause, a confidence, the evidence and the next action. It updates in place rather than adding a comment per run.
|
|
120
|
+
- **In the job summary:** the same failures as a triage board.
|
|
121
|
+
- **As an issue:** environment failures (5xx responses, connection resets, outages) grouped into one issue instead of one per test.
|
|
122
|
+
- **As an artifact** named `tewip-report`: every role's view, including the engineering-quality view with the flaky tests ranked by the CI minutes they cost.
|
|
123
|
+
|
|
124
|
+
## Correcting it
|
|
125
|
+
|
|
126
|
+
When it gets one wrong, reply to its comment:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
/triage TIMING #2 this one is flaky on our CI runners, not a bug
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
From the next run on, that failure of that test gets your answer, shown as "corrected by a person" with your name and reason. A correction settles the cause; it never makes the agent change code.
|
|
133
|
+
|
|
134
|
+
## Asking it questions from your editor
|
|
135
|
+
|
|
136
|
+
- **VS Code, Cursor, Windsurf, VSCodium:** install the Tewip extension (*Extensions → … → Install from VSIX*, `tewip-<version>.vsix`). It connects Tewip to the editor's AI assistant by itself and adds *Tewip: Explain a test report…* and *Tewip: Why did CI fail on this branch?*
|
|
137
|
+
- **JetBrains (2025.2+), Claude, and other MCP clients:** add one server whose command is `tewip mcp`.
|
|
138
|
+
|
|
139
|
+
Then ask, in plain language: "why did CI fail on my PR?", "which tests are flaky in checkout?", "is main safe to release?". Every tool is read-only, and it reads the report the Action already uploaded, so you do not need the other repository cloned.
|
|
140
|
+
|
|
141
|
+
## Stop flaky tests from blocking merges (optional)
|
|
142
|
+
|
|
143
|
+
Once you trust its answers, let the agent decide whether a failed run should block:
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
- name: Tests
|
|
147
|
+
continue-on-error: true # the gate below decides
|
|
148
|
+
run: npx playwright test
|
|
149
|
+
- name: Tewip
|
|
150
|
+
if: always()
|
|
151
|
+
uses: hmamut39/tewip@main
|
|
152
|
+
with:
|
|
153
|
+
gate: real-failures
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The build then fails only for real bugs, changed selectors, test-data problems and anything undecided. Failures a rule or a person classified as flaky or environment no longer block. On 2,296 real failures this unblocked 84% of the flaky and environment ones without letting a real bug through.
|
|
157
|
+
|
|
158
|
+
## Turning fixing on, once you trust it
|
|
159
|
+
|
|
160
|
+
```yaml
|
|
161
|
+
autofix: 'true'
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
It then rewrites a drifted locator, re-runs that single test, and opens a **separate** pull request only with the changes that passed. Review it like any other pull request: an intended UI change and a regression can look identical from the outside, which is exactly why a human merges it.
|
|
165
|
+
|
|
166
|
+
On real WordPress CI data it would have fixed 14 drifted locators with none wrong, and every locator it suggested matched what the developers themselves wrote.
|
|
167
|
+
|
|
168
|
+
## If something does not appear
|
|
169
|
+
|
|
170
|
+
| Symptom | Cause |
|
|
171
|
+
|---|---|
|
|
172
|
+
| The step ran but says "no blob report" | The blob reporter is not on in CI, or the tests step did not run |
|
|
173
|
+
| No comment on the pull request | The run was not triggered by a pull request, or `pull-requests: write` is missing |
|
|
174
|
+
| "Resource not accessible by integration" | The workflow's permissions block is missing an entry |
|
|
175
|
+
| Diagnoses look thin on the first day | The agent judges each failure against that test's history, which it builds from your runs; it gets better as runs accumulate |
|
|
176
|
+
|
|
177
|
+
## What it costs, and what it keeps
|
|
178
|
+
|
|
179
|
+
The agent stores the run history in the Actions cache, never in your repository. Collected failure data and traces stay in CI. The only thing it writes to your repository is a pull request branch, and only when you turn fixing on.
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ It works for every stack: Node.js (node:test, Jest, Vitest, Mocha), Python (pyte
|
|
|
20
20
|
|
|
21
21
|
Formerly *triage-agent*: the repository moved to `hmamut39/tewip`, and GitHub redirects the old address. See [ROADMAP.md](ROADMAP.md) for the plan.
|
|
22
22
|
|
|
23
|
-
**Status:
|
|
23
|
+
**Status: built, and measured on other people's code.** Tewip collects failures from any framework, diagnoses them with rules first and a model only for what rules cannot settle, and turns that into work for each role: a CI comment and merge gate, test plans and verified tests, a flake dossier, a PR-risk review, security scanning, tickets in Jira, Rally, GitHub Issues, Azure Boards or Linear, checks generated from a Figma design, specifications written for people, and - opt in, and only when proved - fixes to test or application code. The fix loops are built and measured, not planned: on real labelled CI failures every one of 17 locator suggestions was the locator the developers themselves wrote, a wait fix is kept only after three passes in a row, and a change to application code is kept only when the failing test passes **and** the whole suite still does. It runs live in GitHub CI and answers questions from AI assistants through MCP. On fresh real Gutenberg CI failures, with the pipeline frozen before labelling, accuracy is 93.4%; across six real datasets it ranges from 86.1% to 99.7%, and the caveats are in [eval/README.md](eval/README.md).
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
## If your CI already writes a coverage report, point Tewip at it
|
|
@@ -1173,9 +1173,25 @@ Two things it refuses to do, which is why the list is worth reading:
|
|
|
1173
1173
|
**Recall, measured by execution** (`eval/vouch-recall.ts`): mutate a source file, record which tests
|
|
1174
1174
|
catch which mutation, remove the last statement of the ones that provably caught something, and run it
|
|
1175
1175
|
all again. A test that caught a mutation before and catches nothing now has provably lost its check -
|
|
1176
|
-
a label that owes nothing to vouch's own patterns.
|
|
1177
|
-
|
|
1178
|
-
|
|
1176
|
+
a label that owes nothing to vouch's own patterns.
|
|
1177
|
+
|
|
1178
|
+
Run across all 48 source/test pairs in this project (Phase 138): 28 produce labelled cases, 22 of
|
|
1179
|
+
those settle, and across them **vouch names 48 of 64 (75.0%)**, with **0 of 157 sound tests wrongly
|
|
1180
|
+
accused**. Precision is the strong half, and it is the half that matters: it did not once accuse a
|
|
1181
|
+
test that still catches something.
|
|
1182
|
+
|
|
1183
|
+
A rate is printed only when two different mutant budgets label the same tests. They often do not,
|
|
1184
|
+
and that is the point: the first run of this reported "2 of 4 (50.0%)" at 8 mutants and **0 of 0** at
|
|
1185
|
+
14 mutants of the same file, because "caught nothing after the deletion" is evidence of hollowness
|
|
1186
|
+
only to the degree that the mutants are many. Six pairs still do not settle and are left out; they
|
|
1187
|
+
were the favourable ones, so 75.0% is a floor.
|
|
1188
|
+
|
|
1189
|
+
Measuring it this way found **two real defects in vouch**, both reporting a hollow test as sound, and
|
|
1190
|
+
neither visible by reading the code: a one-line arrow helper was credited with assertions from the
|
|
1191
|
+
next block in the file, and a test fixture that merely *defines* a stub named `verify` was read as
|
|
1192
|
+
asserting. Fixing them took recall from 58.7% to 70.3% to 75.0%. The figure is measured on this
|
|
1193
|
+
project's own suite rather than on strangers' code, which is weaker evidence than the triage numbers
|
|
1194
|
+
above, and is the next thing to fix. See [eval/README.md](eval/README.md).
|
|
1179
1195
|
|
|
1180
1196
|
## A goal instead of a verb (Phases 19 and 21)
|
|
1181
1197
|
|
|
@@ -1200,6 +1216,39 @@ With `--act` it carries the decision out, and this is where the refusals matter
|
|
|
1200
1216
|
- Everything it did or refused goes to `.tewip/actions.jsonl`, with the run that justified it.
|
|
1201
1217
|
- It **will not repeat itself**: the same attempt is refused until a new run gives it new evidence.
|
|
1202
1218
|
|
|
1219
|
+
## What an IT department has to answer (Phases 133-137)
|
|
1220
|
+
|
|
1221
|
+
Five commands that produce evidence rather than a judgement. All five are rules-only: no model is
|
|
1222
|
+
called, nothing leaves the machine, and every number is re-derivable by running the command again.
|
|
1223
|
+
|
|
1224
|
+
```bash
|
|
1225
|
+
tewip sbom # what shipped, and which licences need a decision
|
|
1226
|
+
tewip infra # what the containers and compose files let in
|
|
1227
|
+
tewip portfolio ~/work # the same page across every repository under a folder
|
|
1228
|
+
tewip audit # who ran what, when, and whether the record was edited
|
|
1229
|
+
tewip safety # what Tewip itself refuses to do
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
- **`sbom`** writes a CycloneDX 1.6 inventory from the lockfile and classifies every licence as
|
|
1233
|
+
permissive, weak or strong copyleft, source-available, **not stated**, or **not recorded**. The
|
|
1234
|
+
last two are different on purpose: "the package declares none" and "this lockfile does not say"
|
|
1235
|
+
are not the same fact, and only the first is the package's doing.
|
|
1236
|
+
- **`infra`** reads Dockerfiles and compose files for the settings that matter in what ships -
|
|
1237
|
+
running as root, a privileged container, the docker socket mounted in - and separates them from
|
|
1238
|
+
the devcontainer and test files, where the same setting is usually fine.
|
|
1239
|
+
- **`portfolio`** runs seven checks over every checkout under a folder and sorts the worst first.
|
|
1240
|
+
The rule that keeps it honest: **a check that could not run prints a dash, never a 0.** At forty
|
|
1241
|
+
rows, a zero meaning "nothing installed" looks exactly like a zero meaning "nothing wrong".
|
|
1242
|
+
- **`audit`** appends one line per run to `.tewip/audit.jsonl`, each carrying the hash of the line
|
|
1243
|
+
before it, so an entry that was changed or removed from the middle is named by line number. Flags
|
|
1244
|
+
whose value is a credential are recorded by name with the value dropped. `--gate` exits non-zero
|
|
1245
|
+
when the chain does not hold, for a nightly check.
|
|
1246
|
+
- **`safety`** is the list of things Tewip will not do, printed by Tewip.
|
|
1247
|
+
|
|
1248
|
+
What `audit` does **not** prove is in its own report, not in a footnote: it does not survive the
|
|
1249
|
+
file being deleted or lines being cut from the end, and it records what was run, not what was true.
|
|
1250
|
+
A tamper-evident log that oversells itself is worse than a plain one, because somebody relies on it.
|
|
1251
|
+
|
|
1203
1252
|
## Where it has been tried
|
|
1204
1253
|
|
|
1205
1254
|
| Project | How | Result |
|
|
@@ -1344,7 +1393,7 @@ npm run triage -- --data data/real/gutenberg-holdout # the same on real CI dat
|
|
|
1344
1393
|
npm run test:engine # unit tests for rules, LLM layer, decide step and views (no network)
|
|
1345
1394
|
```
|
|
1346
1395
|
|
|
1347
|
-
## Auto-fix and the drift lab
|
|
1396
|
+
## Auto-fix and the drift lab
|
|
1348
1397
|
|
|
1349
1398
|
`engine/autofix/` is the ACT + VERIFY loop for LOCATOR_DRIFT. It finds the failing locator in the spec, then tries up to 3 role-based replacements taken from the failure-time page. It re-runs that one test after each attempt, keeps a change only if the test passes, and otherwise restores the file. These safety rules are built into the code:
|
|
1350
1399
|
|