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.
Files changed (51) hide show
  1. package/QUICKSTART.md +178 -178
  2. package/README.md +54 -5
  3. package/dist/cli/help.js +268 -239
  4. package/dist/cli/tewip.js +49 -15
  5. package/dist/cli/verbs-assure.js +54 -0
  6. package/dist/engine/access/access-command.js +8 -3
  7. package/dist/engine/attest/attest.js +37 -2
  8. package/dist/engine/audit/audit-command.js +53 -0
  9. package/dist/engine/audit/audit.js +109 -0
  10. package/dist/engine/autofix/autofix.js +24 -10
  11. package/dist/engine/autofix/code-propose.js +8 -8
  12. package/dist/engine/autofix/fix-data.js +25 -17
  13. package/dist/engine/autofix/fix-wait.js +27 -18
  14. package/dist/engine/build/build-command.js +1 -1
  15. package/dist/engine/build/build.js +22 -22
  16. package/dist/engine/iac/compose.js +74 -0
  17. package/dist/engine/iac/dockerfile.js +79 -0
  18. package/dist/engine/iac/iac-command.js +132 -0
  19. package/dist/engine/incident/incident.js +41 -3
  20. package/dist/engine/learn/learn-command.js +8 -1
  21. package/dist/engine/llm/prompt.js +22 -22
  22. package/dist/engine/llm/usage.js +13 -3
  23. package/dist/engine/notify/note-command.js +6 -2
  24. package/dist/engine/portfolio/portfolio-command.js +144 -0
  25. package/dist/engine/portfolio/portfolio.js +54 -0
  26. package/dist/engine/prove/changed.js +50 -2
  27. package/dist/engine/prove/prove.js +9 -2
  28. package/dist/engine/recall/recall.js +55 -12
  29. package/dist/engine/recall/same.js +116 -0
  30. package/dist/engine/release/channels.js +36 -6
  31. package/dist/engine/safety/safety-command.js +97 -0
  32. package/dist/engine/safety/safety.js +93 -0
  33. package/dist/engine/sbom/inventory.js +179 -0
  34. package/dist/engine/sbom/licences.js +77 -0
  35. package/dist/engine/sbom/sbom-command.js +127 -0
  36. package/dist/engine/schema/migration-files.js +25 -0
  37. package/dist/engine/secure/jwt.js +47 -0
  38. package/dist/engine/secure/secrets.js +8 -42
  39. package/dist/engine/secure/secure-command.js +37 -5
  40. package/dist/engine/secure/triage.js +50 -1
  41. package/dist/engine/taint/flow.js +111 -0
  42. package/dist/engine/verdict/verdict-command.js +9 -2
  43. package/dist/engine/verdict/verdict.js +11 -2
  44. package/dist/engine/vouch/assertions.js +80 -2
  45. package/dist/engine/vouch/text.js +25 -0
  46. package/dist/engine/vouch/vouch.js +23 -2
  47. package/dist/engine/walk.js +67 -0
  48. package/dist/mcp/server.js +1 -1
  49. package/dist/mcp/tools-prove.js +14 -0
  50. package/dist/outlets/items.js +11 -1
  51. 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: phases 1 to 14 are built; the two auto-fix phases (5 and 8) are the ones still in progress.** 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. 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).
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. On 17 such cases across seven source/test pairs in
1177
- two projects, **vouch named 12 (70.6%)**, and the five it did not name still hold a real assertion, so
1178
- it is right about those too. Nothing that still caught a mutation was wrongly accused.
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 (Phase 5, in progress)
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