@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 +13 -13
- package/dist/classifier.d.ts.map +1 -1
- package/dist/classifier.js +88 -4
- package/dist/classifier.js.map +1 -1
- package/dist/classifier.test.d.ts +2 -0
- package/dist/classifier.test.d.ts.map +1 -0
- package/dist/classifier.test.js +68 -0
- package/dist/classifier.test.js.map +1 -0
- package/package.json +4 -3
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
|
|
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);
|
|
32
|
-
console.log(result.confidence);
|
|
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
|
|
56
|
-
|
|
|
57
|
-
| `classifyFailure`
|
|
58
|
-
| `FailureClassifier`
|
|
59
|
-
| `CLASSIFICATION_RULES`
|
|
60
|
-
| `fingerprintFailure`
|
|
61
|
-
| `clusterFailures`
|
|
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
|
-
- [
|
|
74
|
-
- [
|
|
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
|
|
package/dist/classifier.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/classifier.js
CHANGED
|
@@ -107,12 +107,95 @@ exports.CLASSIFICATION_RULES = [
|
|
|
107
107
|
subcategory: 'env_mismatch',
|
|
108
108
|
},
|
|
109
109
|
{
|
|
110
|
-
category: shared_1.FailureCategory.
|
|
111
|
-
patterns: [/
|
|
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
|
-
|
|
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;
|
package/dist/classifier.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -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.
|
|
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.
|
|
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"
|