tewip-ai 0.28.0 → 0.29.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/README.md CHANGED
@@ -632,8 +632,12 @@ Two things it refuses to do, which is why the list is worth reading:
632
632
  test that compiles a TypeScript fixture and runs it asserts nothing *on purpose*. Those are reported
633
633
  separately as "compares no value", not as broken, and they do not trip `--strict`.
634
634
 
635
- Honest limit, also printed at the bottom of every report: its **recall is unmeasured**. A clean report
636
- means nothing it found was wrong, not that every test in the file is worth something.
635
+ **Recall, measured by execution** (`eval/vouch-recall.ts`): mutate a source file, record which tests
636
+ catch which mutation, remove the last statement of the ones that provably caught something, and run it
637
+ all again. A test that caught a mutation before and catches nothing now has provably lost its check -
638
+ a label that owes nothing to vouch's own patterns. On 17 such cases across seven source/test pairs in
639
+ two projects, **vouch named 12 (70.6%)**, and the five it did not name still hold a real assertion, so
640
+ it is right about those too. Nothing that still caught a mutation was wrongly accused.
637
641
 
638
642
  ## A goal instead of a verb (Phases 19 and 21)
639
643
 
@@ -59,7 +59,12 @@ function judge(file, test, helpers) {
59
59
  const at = { file, name: test.name, line: test.line };
60
60
  if (test.skipped)
61
61
  return { ...at, verdict: 'never-runs', evidence: test.name, why: MEANS['never-runs'] };
62
- const body = withoutComments(test.body);
62
+ // Strings are blanked as well as comments. A fixture that quotes `expect(true).toBe(true)` is not a
63
+ // tautology, it is a test *about* tautologies - and before this, Tewip accused its own suite of
64
+ // exactly that. The extractor learned this lesson in Phase 22; the verdicts had not, and it took a
65
+ // recall measurement judging by execution to notice, because no ordinary project quotes test code in
66
+ // its tests. Any checker's own tests do, and so does any test asserting on generated code.
67
+ const body = withoutText(withoutComments(test.body));
63
68
  const tautology = tautologies(body);
64
69
  const unfinished = unfinishedExpectations(body);
65
70
  const checks = checksSomething(body);
@@ -98,6 +103,21 @@ function judge(file, test, helpers) {
98
103
  return { ...at, verdict: 'crash-only', evidence: '(the body is empty)', why: 'the test has no body at all, so nothing can fail it' };
99
104
  return { ...at, verdict: 'crash-only', evidence: firstRealLine(body), why: MEANS['crash-only'] };
100
105
  }
106
+ /**
107
+ * The body with the *contents* of strings and template literals blanked, keeping the quotes and
108
+ * everything around them. `expect(x).toBe(1)` still reads as a call; `"expect(true).toBe(true)"` reads
109
+ * as an empty string.
110
+ */
111
+ function withoutText(body) {
112
+ let out = body;
113
+ for (const [from, to] of textRanges(body).slice().reverse()) {
114
+ const span = out.slice(from, to + 1);
115
+ if (span.length < 3)
116
+ continue;
117
+ out = out.slice(0, from + 1) + ' '.repeat(span.length - 2) + out.slice(to);
118
+ }
119
+ return out;
120
+ }
101
121
  /**
102
122
  * Everything inside a `try` whose `catch` discards what it caught. An assertion failure is an
103
123
  * exception, so a test shaped this way reports success however the code behaves - and a `catch` that
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tewip-ai",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Tewip finds why each failing test failed - real bug, flaky test, environment, test data or changed selector - for any stack, from the command line, CI, or your editor.",
5
5
  "keywords": [
6
6
  "test-failures",