@healflow/classification 0.1.1 → 0.1.3

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
@@ -4,7 +4,7 @@ Rule-based failure classification engine for Playwright and CI test failures.
4
4
 
5
5
  ## Overview
6
6
 
7
- Classifies failures into 14 categories (selector, timing, overlay, iframe, product bug, etc.), computes confidence scores, fingerprints root causes, and clusters duplicate failures.
7
+ Classifies failures into 26 `FailureCategory` values (selector, timing, overlay, iframe, shadow DOM, auth, navigation, product bug, etc.), computes confidence scores, fingerprints root causes, and clusters duplicate failures. Matrix sub-failure matching is enriched in `@healflow/shared` via `enrichClassificationWithMatrix`.
8
8
 
9
9
  **Published to npm** as a transitive dependency. Used by `@healflow/playwright` at runtime and `@healflow/ingestion` during report parsing.
10
10
 
@@ -28,8 +28,8 @@ const result = classifyFailure({
28
28
  source: FailureSource.REPORT,
29
29
  });
30
30
 
31
- console.log(result.category); // e.g. SELECTOR
32
- console.log(result.confidence); // 0–1
31
+ console.log(result.category); // e.g. SELECTOR
32
+ console.log(result.confidence); // 0–1
33
33
  console.log(result.isAutomationFixable);
34
34
  ```
35
35
 
@@ -52,14 +52,14 @@ const score = computeFlakinessScore(history);
52
52
 
53
53
  ## API
54
54
 
55
- | Export | Description |
56
- | ------ | ----------- |
57
- | `classifyFailure` | Classify a single failure event |
58
- | `FailureClassifier` | Stateful classifier with custom rules |
59
- | `CLASSIFICATION_RULES` | Built-in rule definitions |
60
- | `fingerprintFailure` | Stable hash for root-cause grouping |
61
- | `clusterFailures` | Group failures by fingerprint |
62
- | `computeFlakinessScore` | Score flaky test history |
55
+ | Export | Description |
56
+ | ----------------------- | ------------------------------------- |
57
+ | `classifyFailure` | Classify a single failure event |
58
+ | `FailureClassifier` | Stateful classifier with custom rules |
59
+ | `CLASSIFICATION_RULES` | Built-in rule definitions |
60
+ | `fingerprintFailure` | Stable hash for root-cause grouping |
61
+ | `clusterFailures` | Group failures by fingerprint |
62
+ | `computeFlakinessScore` | Score flaky test history |
63
63
 
64
64
  ## Development
65
65
 
@@ -70,8 +70,8 @@ pnpm --filter @healflow/classification test
70
70
 
71
71
  ## Related packages
72
72
 
73
- - [`@healflow/shared`](../shared) — domain types and enums
74
- - [`@healflow/ingestion`](../ingestion) — parses reports then classifies
73
+ - [@healflow/shared](https://www.npmjs.com/package/@healflow/shared) — domain types and enums
74
+ - [@healflow/ingestion](https://www.npmjs.com/package/@healflow/ingestion) — parses reports then classifies
75
75
 
76
76
  ## License
77
77
 
@@ -1 +1 @@
1
- {"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EAEzB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,kBAAkB,EA4GpD,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAW;gBAElC,OAAO,GAAE,iBAAsB;IAO3C,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,oBAAoB;CAsEtD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,oBAAoB,CAE3E"}
1
+ {"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EAEzB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAO1B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,kBAAkB,EA+LpD,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAW;gBAElC,OAAO,GAAE,iBAAsB;IAO3C,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,oBAAoB;CAwEtD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,oBAAoB,CAE3E"}
@@ -107,12 +107,95 @@ exports.CLASSIFICATION_RULES = [
107
107
  subcategory: 'env_mismatch',
108
108
  },
109
109
  {
110
- category: shared_1.FailureCategory.PRODUCT_BUG,
111
- patterns: [/assertion.*failed/i, /expected.*received/i, /toEqual|toBe\(/i],
110
+ category: shared_1.FailureCategory.NAVIGATION,
111
+ patterns: [/waitForURL/i, /page\.url/i, /navigation.*failed/i, /redirect/i, /404|500 page/i],
112
+ weight: 0.75,
113
+ subcategory: 'navigation_failure',
114
+ },
115
+ {
116
+ category: shared_1.FailureCategory.VISUAL,
117
+ patterns: [/toHaveScreenshot/i, /toMatchAriaSnapshot/i, /screenshot/i, /pixel diff/i],
118
+ weight: 0.7,
119
+ subcategory: 'visual_snapshot',
120
+ },
121
+ {
122
+ category: shared_1.FailureCategory.I18N,
123
+ patterns: [/locale/i, /i18n/i, /translation/i, /Intl\./i, /RTL/i],
124
+ weight: 0.7,
125
+ subcategory: 'i18n_mismatch',
126
+ },
127
+ {
128
+ category: shared_1.FailureCategory.MOBILE,
129
+ patterns: [/tap\(/i, /swipe/i, /touch/i, /mobile viewport/i],
130
+ weight: 0.7,
131
+ subcategory: 'mobile_gesture',
132
+ },
133
+ {
134
+ category: shared_1.FailureCategory.UPLOAD,
135
+ patterns: [/setInputFiles/i, /download/i, /clipboard/i, /upload/i],
136
+ weight: 0.7,
137
+ subcategory: 'upload_download',
138
+ },
139
+ {
140
+ category: shared_1.FailureCategory.MULTI_TAB,
141
+ patterns: [/waitForEvent\(['"]popup/i, /popup/i, /new tab/i, /context\.pages/i],
142
+ weight: 0.75,
143
+ subcategory: 'multi_tab',
144
+ },
145
+ {
146
+ category: shared_1.FailureCategory.PERFORMANCE,
147
+ patterns: [/test timeout/i, /memory/i, /infinite scroll/i, /too slow/i],
148
+ weight: 0.65,
149
+ subcategory: 'performance',
150
+ },
151
+ {
152
+ category: shared_1.FailureCategory.THIRD_PARTY,
153
+ patterns: [/stripe/i, /maps widget/i, /chat widget/i, /social login/i],
154
+ weight: 0.65,
155
+ subcategory: 'third_party',
156
+ },
157
+ {
158
+ category: shared_1.FailureCategory.TEST_STRUCTURE,
159
+ patterns: [/Cannot find module/i, /import.*fixture/i, /syntax error/i],
112
160
  weight: 0.6,
161
+ subcategory: 'test_structure',
162
+ },
163
+ {
164
+ category: shared_1.FailureCategory.ASSERTION,
165
+ patterns: [
166
+ /expect\(.*\)\.(?:toBe|toEqual|toContain|toMatch|toHaveText|toHaveCount|toHaveURL)/i,
167
+ /assertion.*failed/i,
168
+ /expected.*received/i,
169
+ ],
170
+ weight: 0.85,
113
171
  isProductBug: true,
114
172
  subcategory: 'assertion_failure',
115
173
  },
174
+ {
175
+ category: shared_1.FailureCategory.SECURITY,
176
+ patterns: [/captcha/i, /mfa|2fa/i, /pci/i, /secret.*in.*source/i],
177
+ weight: 0.9,
178
+ subcategory: 'security_boundary',
179
+ },
180
+ {
181
+ category: shared_1.FailureCategory.BROWSER_INFRA,
182
+ patterns: [
183
+ /browser.*crash/i,
184
+ /out of memory/i,
185
+ /playwright.*version/i,
186
+ /disk full/i,
187
+ /browserType\.launch/i,
188
+ ],
189
+ weight: 0.65,
190
+ subcategory: 'browser_infra',
191
+ },
192
+ {
193
+ category: shared_1.FailureCategory.PRODUCT_BUG,
194
+ patterns: [/missing button/i, /500 error page/i, /wrong business/i, /data corruption/i],
195
+ weight: 0.6,
196
+ isProductBug: true,
197
+ subcategory: 'product_defect',
198
+ },
116
199
  ];
117
200
  class FailureClassifier {
118
201
  rules;
@@ -120,7 +203,7 @@ class FailureClassifier {
120
203
  constructor(options = {}) {
121
204
  this.rules = options.rules ?? exports.CLASSIFICATION_RULES;
122
205
  this.productBugPatterns = options.productBugPatterns ?? [
123
- /expect\(.*\)\.(?:toBe|toEqual|toContain|toMatch)/i,
206
+ /expect\(.*\)\.(?:toBe|toEqual|toContain|toMatch|toHaveText|toHaveCount)/i,
124
207
  ];
125
208
  }
126
209
  classify(failure) {
@@ -180,11 +263,12 @@ class FailureClassifier {
180
263
  detectedAt: new Date().toISOString(),
181
264
  };
182
265
  const { outcome, recommendedAction } = (0, shared_2.resolveFailureOutcome)(base);
183
- return {
266
+ const withOutcome = {
184
267
  ...base,
185
268
  healOutcome: outcome,
186
269
  recommendedAction,
187
270
  };
271
+ return (0, shared_2.enrichClassificationWithMatrix)(withOutcome, haystack);
188
272
  }
189
273
  }
190
274
  exports.FailureClassifier = FailureClassifier;
@@ -1 +1 @@
1
- {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=classifier.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.test.d.ts","sourceRoot":"","sources":["../src/classifier.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = require("node:test");
8
+ const classifier_js_1 = require("./classifier.js");
9
+ const shared_1 = require("@healflow/shared");
10
+ (0, node_test_1.describe)('FailureClassifier matrix integration', () => {
11
+ (0, node_test_1.it)('enriches selector failures with matrix metadata', () => {
12
+ const result = (0, classifier_js_1.classifyFailure)({
13
+ id: 'f1',
14
+ organizationId: 'org',
15
+ repositoryId: 'repo',
16
+ source: shared_1.FailureSource.REPORT,
17
+ testFile: 'tests/checkout.spec.ts',
18
+ testTitle: 'checkout',
19
+ errorMessage: "waiting for getByTestId('checkout-btn') strict mode violation",
20
+ artifacts: [],
21
+ metadata: {},
22
+ occurredAt: new Date().toISOString(),
23
+ fingerprint: 'fp',
24
+ });
25
+ strict_1.default.equal(result.category, shared_1.FailureCategory.SELECTOR);
26
+ strict_1.default.ok(result.matrixEntryId);
27
+ strict_1.default.ok((result.techniqueStack?.length ?? 0) > 0);
28
+ strict_1.default.equal(result.healOutcome, shared_1.HealOutcome.HEALED);
29
+ });
30
+ (0, node_test_1.it)('classifies assertion failures as ASSERTION and blocks healing', () => {
31
+ const result = (0, classifier_js_1.classifyFailure)({
32
+ id: 'f2',
33
+ organizationId: 'org',
34
+ repositoryId: 'repo',
35
+ source: shared_1.FailureSource.REPORT,
36
+ testFile: 'tests/pricing.spec.ts',
37
+ testTitle: 'price',
38
+ errorMessage: 'expect(received).toHaveText expected $29.99 received $19.99',
39
+ artifacts: [],
40
+ metadata: {},
41
+ occurredAt: new Date().toISOString(),
42
+ fingerprint: 'fp2',
43
+ });
44
+ strict_1.default.equal(result.category, shared_1.FailureCategory.ASSERTION);
45
+ strict_1.default.equal(result.healOutcome, shared_1.HealOutcome.BLOCKED);
46
+ strict_1.default.equal(result.matrixEntryId, 'assert.value_mismatch');
47
+ });
48
+ (0, node_test_1.it)('diagnoses network failures despite partial matrix healability', () => {
49
+ const result = (0, classifier_js_1.classifyFailure)({
50
+ id: 'f3',
51
+ organizationId: 'org',
52
+ repositoryId: 'repo',
53
+ source: shared_1.FailureSource.REPORT,
54
+ testFile: 'tests/api.spec.ts',
55
+ testTitle: 'api',
56
+ errorMessage: 'net::ERR_CONNECTION_REFUSED ECONNREFUSED',
57
+ artifacts: [],
58
+ metadata: {},
59
+ occurredAt: new Date().toISOString(),
60
+ fingerprint: 'fp3',
61
+ });
62
+ strict_1.default.equal(result.category, shared_1.FailureCategory.NETWORK);
63
+ strict_1.default.equal(result.healOutcome, shared_1.HealOutcome.DIAGNOSED);
64
+ strict_1.default.equal(result.matrixEntryId, 'network.transient');
65
+ strict_1.default.ok(result.techniqueStack?.includes(shared_1.HealingTechnique.T0_RETRY));
66
+ });
67
+ });
68
+ //# sourceMappingURL=classifier.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.test.js","sourceRoot":"","sources":["../src/classifier.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "@healflow/classification",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "HealFlow failure classification engine",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "dependencies": {
8
- "@healflow/shared": "^0.1.1"
8
+ "@healflow/shared": "^0.1.3"
9
9
  },
10
10
  "devDependencies": {
11
11
  "tsx": "^4.19.2",
12
- "typescript": "^5.7.2"
12
+ "typescript": "^5.7.2",
13
+ "vitest": "^3.2.4"
13
14
  },
14
15
  "files": [
15
16
  "dist"