@aiready/testability 0.6.1 → 0.6.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.
@@ -0,0 +1,270 @@
1
+ {
2
+ "summary": {
3
+ "totalIssues": 0,
4
+ "criticalIssues": 0,
5
+ "majorIssues": 0,
6
+ "totalFiles": 0,
7
+ "toolsRun": ["testability-index"],
8
+ "executionTime": 41,
9
+ "config": {
10
+ "scan": {
11
+ "tools": ["testability-index"]
12
+ },
13
+ "tools": {
14
+ "testability-index": {}
15
+ }
16
+ },
17
+ "toolConfigs": {
18
+ "testability-index": {}
19
+ }
20
+ },
21
+ "testability-index": {
22
+ "results": [],
23
+ "summary": {
24
+ "score": 47,
25
+ "sourceFiles": 6,
26
+ "testFiles": 4,
27
+ "coverageRatio": 0.67,
28
+ "rating": "poor",
29
+ "aiChangeSafetyRating": "high-risk",
30
+ "dimensions": {
31
+ "testCoverageRatio": 67,
32
+ "purityScore": 50,
33
+ "dependencyInjectionScore": 0,
34
+ "interfaceFocusScore": 73,
35
+ "observabilityScore": 50
36
+ }
37
+ },
38
+ "metadata": {
39
+ "toolName": "testability-index",
40
+ "version": "0.2.5",
41
+ "timestamp": "2026-03-14T11:52:28.204Z",
42
+ "rawData": {
43
+ "sourceFiles": 6,
44
+ "testFiles": 4,
45
+ "pureFunctions": 1,
46
+ "totalFunctions": 2,
47
+ "injectionPatterns": 0,
48
+ "totalClasses": 0,
49
+ "bloatedInterfaces": 1,
50
+ "totalInterfaces": 3,
51
+ "externalStateMutations": 1,
52
+ "hasTestFramework": true
53
+ },
54
+ "config": {}
55
+ }
56
+ },
57
+ "testability": {
58
+ "results": [],
59
+ "summary": {
60
+ "score": 47,
61
+ "sourceFiles": 6,
62
+ "testFiles": 4,
63
+ "coverageRatio": 0.67,
64
+ "rating": "poor",
65
+ "aiChangeSafetyRating": "high-risk",
66
+ "dimensions": {
67
+ "testCoverageRatio": 67,
68
+ "purityScore": 50,
69
+ "dependencyInjectionScore": 0,
70
+ "interfaceFocusScore": 73,
71
+ "observabilityScore": 50
72
+ }
73
+ },
74
+ "metadata": {
75
+ "toolName": "testability-index",
76
+ "version": "0.2.5",
77
+ "timestamp": "2026-03-14T11:52:28.204Z",
78
+ "rawData": {
79
+ "sourceFiles": 6,
80
+ "testFiles": 4,
81
+ "pureFunctions": 1,
82
+ "totalFunctions": 2,
83
+ "injectionPatterns": 0,
84
+ "totalClasses": 0,
85
+ "bloatedInterfaces": 1,
86
+ "totalInterfaces": 3,
87
+ "externalStateMutations": 1,
88
+ "hasTestFramework": true
89
+ },
90
+ "config": {}
91
+ }
92
+ },
93
+ "tests": {
94
+ "results": [],
95
+ "summary": {
96
+ "score": 47,
97
+ "sourceFiles": 6,
98
+ "testFiles": 4,
99
+ "coverageRatio": 0.67,
100
+ "rating": "poor",
101
+ "aiChangeSafetyRating": "high-risk",
102
+ "dimensions": {
103
+ "testCoverageRatio": 67,
104
+ "purityScore": 50,
105
+ "dependencyInjectionScore": 0,
106
+ "interfaceFocusScore": 73,
107
+ "observabilityScore": 50
108
+ }
109
+ },
110
+ "metadata": {
111
+ "toolName": "testability-index",
112
+ "version": "0.2.5",
113
+ "timestamp": "2026-03-14T11:52:28.204Z",
114
+ "rawData": {
115
+ "sourceFiles": 6,
116
+ "testFiles": 4,
117
+ "pureFunctions": 1,
118
+ "totalFunctions": 2,
119
+ "injectionPatterns": 0,
120
+ "totalClasses": 0,
121
+ "bloatedInterfaces": 1,
122
+ "totalInterfaces": 3,
123
+ "externalStateMutations": 1,
124
+ "hasTestFramework": true
125
+ },
126
+ "config": {}
127
+ }
128
+ },
129
+ "verification": {
130
+ "results": [],
131
+ "summary": {
132
+ "score": 47,
133
+ "sourceFiles": 6,
134
+ "testFiles": 4,
135
+ "coverageRatio": 0.67,
136
+ "rating": "poor",
137
+ "aiChangeSafetyRating": "high-risk",
138
+ "dimensions": {
139
+ "testCoverageRatio": 67,
140
+ "purityScore": 50,
141
+ "dependencyInjectionScore": 0,
142
+ "interfaceFocusScore": 73,
143
+ "observabilityScore": 50
144
+ }
145
+ },
146
+ "metadata": {
147
+ "toolName": "testability-index",
148
+ "version": "0.2.5",
149
+ "timestamp": "2026-03-14T11:52:28.204Z",
150
+ "rawData": {
151
+ "sourceFiles": 6,
152
+ "testFiles": 4,
153
+ "pureFunctions": 1,
154
+ "totalFunctions": 2,
155
+ "injectionPatterns": 0,
156
+ "totalClasses": 0,
157
+ "bloatedInterfaces": 1,
158
+ "totalInterfaces": 3,
159
+ "externalStateMutations": 1,
160
+ "hasTestFramework": true
161
+ },
162
+ "config": {}
163
+ }
164
+ },
165
+ "testabilityIndex": {
166
+ "results": [],
167
+ "summary": {
168
+ "score": 47,
169
+ "sourceFiles": 6,
170
+ "testFiles": 4,
171
+ "coverageRatio": 0.67,
172
+ "rating": "poor",
173
+ "aiChangeSafetyRating": "high-risk",
174
+ "dimensions": {
175
+ "testCoverageRatio": 67,
176
+ "purityScore": 50,
177
+ "dependencyInjectionScore": 0,
178
+ "interfaceFocusScore": 73,
179
+ "observabilityScore": 50
180
+ }
181
+ },
182
+ "metadata": {
183
+ "toolName": "testability-index",
184
+ "version": "0.2.5",
185
+ "timestamp": "2026-03-14T11:52:28.204Z",
186
+ "rawData": {
187
+ "sourceFiles": 6,
188
+ "testFiles": 4,
189
+ "pureFunctions": 1,
190
+ "totalFunctions": 2,
191
+ "injectionPatterns": 0,
192
+ "totalClasses": 0,
193
+ "bloatedInterfaces": 1,
194
+ "totalInterfaces": 3,
195
+ "externalStateMutations": 1,
196
+ "hasTestFramework": true
197
+ },
198
+ "config": {}
199
+ }
200
+ },
201
+ "results": [],
202
+ "scoring": {
203
+ "overall": 47,
204
+ "rating": "Needs Work",
205
+ "timestamp": "2026-03-14T11:52:28.205Z",
206
+ "toolsUsed": ["testability-index"],
207
+ "breakdown": [
208
+ {
209
+ "toolName": "testability-index",
210
+ "score": 47,
211
+ "rawMetrics": {
212
+ "sourceFiles": 6,
213
+ "testFiles": 4,
214
+ "pureFunctions": 1,
215
+ "totalFunctions": 2,
216
+ "injectionPatterns": 0,
217
+ "totalClasses": 0,
218
+ "bloatedInterfaces": 1,
219
+ "totalInterfaces": 3,
220
+ "externalStateMutations": 1,
221
+ "hasTestFramework": true,
222
+ "rating": "poor",
223
+ "aiChangeSafetyRating": "high-risk",
224
+ "coverageRatio": 0.67
225
+ },
226
+ "factors": [
227
+ {
228
+ "name": "Test Coverage",
229
+ "impact": 17,
230
+ "description": "4 test files / 6 source files (67%)"
231
+ },
232
+ {
233
+ "name": "Function Purity",
234
+ "impact": 0,
235
+ "description": "1/2 functions are pure"
236
+ },
237
+ {
238
+ "name": "Dependency Injection",
239
+ "impact": -50,
240
+ "description": "0/0 classes use DI"
241
+ },
242
+ {
243
+ "name": "Interface Focus",
244
+ "impact": 23,
245
+ "description": "1 interfaces have >10 methods"
246
+ },
247
+ {
248
+ "name": "Observability",
249
+ "impact": 0,
250
+ "description": "1 functions mutate external state"
251
+ }
252
+ ],
253
+ "recommendations": []
254
+ }
255
+ ],
256
+ "calculation": {
257
+ "formula": "[(47 × 10)] / 10 = 47",
258
+ "weights": {
259
+ "testability-index": 10
260
+ },
261
+ "normalized": "[(47 × 10)] / 10 = 47"
262
+ }
263
+ },
264
+ "repository": {
265
+ "url": "https://github.com/caopengau/aiready.git",
266
+ "branch": "main",
267
+ "commit": "3be4936e1c8aa50d6324b014ca8fcf791c6dcfaf",
268
+ "author": "caopengau@gmail.com"
269
+ }
270
+ }
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/testability@0.6.0 build /Users/pengcao/projects/aiready/packages/testability
3
+ > @aiready/testability@0.6.3 build /Users/pengcao/projects/aiready/packages/testability
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -10,15 +10,15 @@
10
10
  CJS Build start
11
11
  ESM Build start
12
12
  CJS dist/cli.js 15.61 KB
13
- CJS dist/index.js 10.73 KB
14
- CJS ⚡️ Build success in 41ms
15
- ESM dist/index.mjs 1.28 KB
16
- ESM dist/cli.mjs 5.75 KB
13
+ CJS dist/index.js 10.61 KB
14
+ CJS ⚡️ Build success in 81ms
15
+ ESM dist/index.mjs 1.17 KB
17
16
  ESM dist/chunk-QOIBI5E7.mjs 8.31 KB
18
- ESM ⚡️ Build success in 40ms
17
+ ESM dist/cli.mjs 5.75 KB
18
+ ESM ⚡️ Build success in 81ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 1497ms
20
+ DTS ⚡️ Build success in 3042ms
21
21
  DTS dist/cli.d.ts 20.00 B
22
- DTS dist/index.d.ts 2.41 KB
22
+ DTS dist/index.d.ts 2.45 KB
23
23
  DTS dist/cli.d.mts 20.00 B
24
- DTS dist/index.d.mts 2.41 KB
24
+ DTS dist/index.d.mts 2.45 KB
@@ -1,6 +1,10 @@
1
-
2
- 
3
- > @aiready/testability@0.4.18 lint /Users/pengcao/projects/aiready/packages/testability
4
- > eslint src
5
-
6
-  ELIFECYCLE  Command failed.
1
+
2
+ > @aiready/testability@0.6.2 lint /Users/pengcao/projects/aiready/packages/testability
3
+ > eslint src
4
+
5
+
6
+ /Users/pengcao/projects/aiready/packages/testability/src/analyzer.ts
7
+ 8:3 warning 'Language' is defined but never used @typescript-eslint/no-unused-vars
8
+
9
+ ✖ 1 problem (0 errors, 1 warning)
10
+
@@ -1,114 +1,20 @@
1
1
 
2
2
  
3
- > @aiready/testability@0.6.0 test /Users/pengcao/projects/aiready/packages/testability
3
+ > @aiready/testability@0.6.2 test /Users/pengcao/projects/aiready/packages/testability
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.18 /Users/pengcao/projects/aiready/packages/testability
8
8
 
9
- [?2026h
10
-  ❯ src/__tests__/provider.test.ts [queued]
11
-
12
-  Test Files 0 passed (4)
13
-  Tests 0 passed (0)
14
-  Start at 17:20:11
15
-  Duration 731ms
16
- [?2026l[?2026h
17
-  ❯ src/__tests__/provider.test.ts [queued]
18
-  ❯ src/__tests__/types.test.ts [queued]
19
-
20
-  Test Files 0 passed (4)
21
-  Tests 0 passed (0)
22
-  Start at 17:20:11
23
-  Duration 833ms
24
- [?2026l[?2026h
25
-  ❯ src/__tests__/analyzer.test.ts [queued]
26
-  ❯ src/__tests__/provider.test.ts [queued]
27
-  ❯ src/__tests__/scoring.test.ts [queued]
28
-  ❯ src/__tests__/types.test.ts [queued]
29
-
30
-  Test Files 0 passed (4)
31
-  Tests 0 passed (0)
32
-  Start at 17:20:11
33
-  Duration 1.17s
34
- [?2026l[?2026h
35
-  ❯ src/__tests__/analyzer.test.ts [queued]
36
-  ❯ src/__tests__/provider.test.ts [queued]
37
-  ❯ src/__tests__/scoring.test.ts [queued]
38
-  ❯ src/__tests__/types.test.ts 0/4
39
-
40
-  Test Files 0 passed (4)
41
-  Tests 0 passed (4)
42
-  Start at 17:20:11
43
-  Duration 1.32s
44
- [?2026l[?2026h
45
-  ❯ src/__tests__/analyzer.test.ts [queued]
46
-  ❯ src/__tests__/provider.test.ts [queued]
47
-  ❯ src/__tests__/scoring.test.ts [queued]
48
-  ❯ src/__tests__/types.test.ts 1/4
49
-
50
-  Test Files 0 passed (4)
51
-  Tests 1 passed (4)
52
-  Start at 17:20:11
53
-  Duration 1.62s
54
- [?2026l[?2026h ✓ src/__tests__/types.test.ts (4 tests) 140ms
55
-
56
-  ❯ src/__tests__/analyzer.test.ts [queued]
57
-  ❯ src/__tests__/provider.test.ts [queued]
58
-  ❯ src/__tests__/scoring.test.ts [queued]
59
-
60
-  Test Files 1 passed (4)
61
-  Tests 4 passed (4)
62
-  Start at 17:20:11
63
-  Duration 2.11s
64
- [?2026l[?2026h
65
-  ❯ src/__tests__/analyzer.test.ts [queued]
66
-  ❯ src/__tests__/provider.test.ts [queued]
67
-  ❯ src/__tests__/scoring.test.ts [queued]
68
-
69
-  Test Files 1 passed (4)
70
-  Tests 4 passed (4)
71
-  Start at 17:20:11
72
-  Duration 3.07s
73
- [?2026l[?2026h
74
-  ❯ src/__tests__/analyzer.test.ts [queued]
75
-  ❯ src/__tests__/provider.test.ts 0/2
76
-  ❯ src/__tests__/scoring.test.ts [queued]
77
-
78
-  Test Files 1 passed (4)
79
-  Tests 4 passed (6)
80
-  Start at 17:20:11
81
-  Duration 3.37s
82
- [?2026l[?2026h ✓ src/__tests__/provider.test.ts (2 tests) 5ms
83
-
84
-  ❯ src/__tests__/analyzer.test.ts 0/5
85
-  ❯ src/__tests__/scoring.test.ts [queued]
86
-
87
-  Test Files 2 passed (4)
88
-  Tests 6 passed (11)
89
-  Start at 17:20:11
90
-  Duration 3.48s
91
- [?2026l[?2026h ✓ src/__tests__/scoring.test.ts (3 tests) 23ms
92
-
93
-  ❯ src/__tests__/analyzer.test.ts 0/5
94
-
95
-  Test Files 3 passed (4)
96
-  Tests 9 passed (14)
97
-  Start at 17:20:11
98
-  Duration 4.08s
99
- [?2026l[?2026h
100
-  ❯ src/__tests__/analyzer.test.ts 1/5
101
-
102
-  Test Files 3 passed (4)
103
-  Tests 10 passed (14)
104
-  Start at 17:20:11
105
-  Duration 4.79s
106
- [?2026l ✓ src/__tests__/analyzer.test.ts (5 tests) 1345ms
107
- ✓ detects test frameworks in multiple languages  1319ms
9
+ ✓ src/__tests__/types.test.ts (4 tests) 13ms
10
+ ✓ src/__tests__/provider.test.ts (2 tests) 200ms
11
+ ✓ src/__tests__/scoring.test.ts (3 tests) 4ms
12
+ ✓ src/__tests__/analyzer.test.ts (5 tests) 4213ms
13
+ ✓ detects test frameworks in multiple languages  4166ms
108
14
 
109
15
   Test Files  4 passed (4)
110
16
   Tests  14 passed (14)
111
-  Start at  17:20:11
112
-  Duration  4.90s (transform 3.18s, setup 0ms, import 8.22s, tests 1.51s, environment 0ms)
17
+  Start at  22:22:02
18
+  Duration  6.84s (transform 2.03s, setup 0ms, import 6.37s, tests 4.43s, environment 0ms)
113
19
 
114
20
  [?25h
package/dist/index.d.mts CHANGED
@@ -1,9 +1,10 @@
1
- import { ToolProvider, Issue, IssueType, ToolScoringOutput } from '@aiready/core';
1
+ import * as _aiready_core from '@aiready/core';
2
+ import { Issue, IssueType, ToolScoringOutput } from '@aiready/core';
2
3
 
3
4
  /**
4
5
  * Testability Tool Provider
5
6
  */
6
- declare const TestabilityProvider: ToolProvider;
7
+ declare const TestabilityProvider: _aiready_core.ToolProvider;
7
8
 
8
9
  interface TestabilityOptions {
9
10
  /** Root directory to scan */
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { ToolProvider, Issue, IssueType, ToolScoringOutput } from '@aiready/core';
1
+ import * as _aiready_core from '@aiready/core';
2
+ import { Issue, IssueType, ToolScoringOutput } from '@aiready/core';
2
3
 
3
4
  /**
4
5
  * Testability Tool Provider
5
6
  */
6
- declare const TestabilityProvider: ToolProvider;
7
+ declare const TestabilityProvider: _aiready_core.ToolProvider;
7
8
 
8
9
  interface TestabilityOptions {
9
10
  /** Root directory to scan */
package/dist/index.js CHANGED
@@ -282,39 +282,38 @@ function calculateTestabilityScore(report) {
282
282
  }
283
283
 
284
284
  // src/provider.ts
285
- var TestabilityProvider = {
285
+ var TestabilityProvider = (0, import_core3.createProvider)({
286
286
  id: import_core3.ToolName.TestabilityIndex,
287
287
  alias: ["testability", "tests", "verification"],
288
- async analyze(options) {
289
- const report = await analyzeTestability(options);
290
- const results = report.issues.map((i) => ({
291
- fileName: i.location.file,
292
- issues: [i],
288
+ version: "0.2.5",
289
+ defaultWeight: 10,
290
+ async analyzeReport(options) {
291
+ return analyzeTestability(options);
292
+ },
293
+ getResults(report) {
294
+ return report.issues.map((issue) => ({
295
+ fileName: issue.location.file,
296
+ issues: [issue],
293
297
  metrics: {
294
298
  testabilityScore: report.summary.score
295
299
  }
296
300
  }));
297
- return import_core3.SpokeOutputSchema.parse({
298
- results,
299
- summary: report.summary,
300
- metadata: {
301
- toolName: import_core3.ToolName.TestabilityIndex,
302
- version: "0.2.5",
303
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
304
- rawData: report.rawData
305
- }
306
- });
307
301
  },
308
- score(output, options) {
302
+ getSummary(report) {
303
+ return report.summary;
304
+ },
305
+ getMetadata(report) {
306
+ return { rawData: report.rawData };
307
+ },
308
+ score(output) {
309
309
  const report = {
310
310
  summary: output.summary,
311
311
  rawData: output.metadata.rawData,
312
312
  recommendations: output.summary.recommendations || []
313
313
  };
314
314
  return calculateTestabilityScore(report);
315
- },
316
- defaultWeight: 10
317
- };
315
+ }
316
+ });
318
317
 
319
318
  // src/index.ts
320
319
  import_core4.ToolRegistry.register(TestabilityProvider);
package/dist/index.mjs CHANGED
@@ -8,42 +8,41 @@ import { ToolRegistry } from "@aiready/core";
8
8
 
9
9
  // src/provider.ts
10
10
  import {
11
- ToolName,
12
- SpokeOutputSchema
11
+ createProvider,
12
+ ToolName
13
13
  } from "@aiready/core";
14
- var TestabilityProvider = {
14
+ var TestabilityProvider = createProvider({
15
15
  id: ToolName.TestabilityIndex,
16
16
  alias: ["testability", "tests", "verification"],
17
- async analyze(options) {
18
- const report = await analyzeTestability(options);
19
- const results = report.issues.map((i) => ({
20
- fileName: i.location.file,
21
- issues: [i],
17
+ version: "0.2.5",
18
+ defaultWeight: 10,
19
+ async analyzeReport(options) {
20
+ return analyzeTestability(options);
21
+ },
22
+ getResults(report) {
23
+ return report.issues.map((issue) => ({
24
+ fileName: issue.location.file,
25
+ issues: [issue],
22
26
  metrics: {
23
27
  testabilityScore: report.summary.score
24
28
  }
25
29
  }));
26
- return SpokeOutputSchema.parse({
27
- results,
28
- summary: report.summary,
29
- metadata: {
30
- toolName: ToolName.TestabilityIndex,
31
- version: "0.2.5",
32
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
33
- rawData: report.rawData
34
- }
35
- });
36
30
  },
37
- score(output, options) {
31
+ getSummary(report) {
32
+ return report.summary;
33
+ },
34
+ getMetadata(report) {
35
+ return { rawData: report.rawData };
36
+ },
37
+ score(output) {
38
38
  const report = {
39
39
  summary: output.summary,
40
40
  rawData: output.metadata.rawData,
41
41
  recommendations: output.summary.recommendations || []
42
42
  };
43
43
  return calculateTestabilityScore(report);
44
- },
45
- defaultWeight: 10
46
- };
44
+ }
45
+ });
47
46
 
48
47
  // src/index.ts
49
48
  ToolRegistry.register(TestabilityProvider);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/testability",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Measures how safely and verifiably AI-generated changes can be made to your codebase",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -40,7 +40,7 @@
40
40
  "chalk": "^5.3.0",
41
41
  "commander": "^14.0.0",
42
42
  "glob": "^13.0.0",
43
- "@aiready/core": "0.23.1"
43
+ "@aiready/core": "0.23.3"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^24.0.0",
@@ -18,7 +18,7 @@ describe('Testability Provider', () => {
18
18
  const output = await TestabilityProvider.analyze({ rootDir: '.' });
19
19
 
20
20
  expect(output.summary.score).toBe(90);
21
- expect(output.metadata.toolName).toBe('testability-index');
21
+ expect(output.metadata!.toolName).toBe('testability-index');
22
22
  });
23
23
 
24
24
  it('should score an output', () => {
package/src/analyzer.ts CHANGED
@@ -5,7 +5,6 @@ import {
5
5
  IssueType,
6
6
  emitProgress,
7
7
  getParser,
8
- Language,
9
8
  } from '@aiready/core';
10
9
  import { readFileSync, existsSync } from 'fs';
11
10
  import { join } from 'path';
@@ -115,7 +114,9 @@ function detectTestFramework(rootDir: string): boolean {
115
114
  try {
116
115
  const content = readFileSync(p, 'utf-8');
117
116
  if (m.deps.some((d) => content.includes(d))) return true;
118
- } catch {}
117
+ } catch {
118
+ // Ignore file read errors
119
+ }
119
120
  }
120
121
  }
121
122
  return false;
package/src/provider.ts CHANGED
@@ -1,11 +1,8 @@
1
1
  import {
2
- ToolProvider,
2
+ AnalysisResult,
3
+ createProvider,
3
4
  ToolName,
4
- SpokeOutput,
5
5
  ScanOptions,
6
- ToolScoringOutput,
7
- AnalysisResult,
8
- SpokeOutputSchema,
9
6
  } from '@aiready/core';
10
7
  import { analyzeTestability } from './analyzer';
11
8
  import { calculateTestabilityScore } from './scoring';
@@ -14,42 +11,35 @@ import { TestabilityOptions, TestabilityReport } from './types';
14
11
  /**
15
12
  * Testability Tool Provider
16
13
  */
17
- export const TestabilityProvider: ToolProvider = {
14
+ export const TestabilityProvider = createProvider({
18
15
  id: ToolName.TestabilityIndex,
19
16
  alias: ['testability', 'tests', 'verification'],
20
-
21
- async analyze(options: ScanOptions): Promise<SpokeOutput> {
22
- const report = await analyzeTestability(options as TestabilityOptions);
23
-
24
- const results: AnalysisResult[] = report.issues.map((i) => ({
25
- fileName: i.location.file,
26
- issues: [i] as any[],
17
+ version: '0.2.5',
18
+ defaultWeight: 10,
19
+ async analyzeReport(options: ScanOptions) {
20
+ return analyzeTestability(options as TestabilityOptions);
21
+ },
22
+ getResults(report): AnalysisResult[] {
23
+ return report.issues.map((issue) => ({
24
+ fileName: issue.location.file,
25
+ issues: [issue] as any[],
27
26
  metrics: {
28
27
  testabilityScore: report.summary.score,
29
28
  },
30
29
  }));
31
-
32
- return SpokeOutputSchema.parse({
33
- results,
34
- summary: report.summary,
35
- metadata: {
36
- toolName: ToolName.TestabilityIndex,
37
- version: '0.2.5',
38
- timestamp: new Date().toISOString(),
39
- rawData: report.rawData,
40
- },
41
- });
42
30
  },
43
-
44
- score(output: SpokeOutput, options: ScanOptions): ToolScoringOutput {
31
+ getSummary(report) {
32
+ return report.summary;
33
+ },
34
+ getMetadata(report) {
35
+ return { rawData: report.rawData };
36
+ },
37
+ score(output) {
45
38
  const report = {
46
39
  summary: output.summary,
47
40
  rawData: (output.metadata as any).rawData,
48
41
  recommendations: (output.summary as any).recommendations || [],
49
42
  } as unknown as TestabilityReport;
50
-
51
43
  return calculateTestabilityScore(report);
52
44
  },
53
-
54
- defaultWeight: 10,
55
- };
45
+ });