@nebutra/next-unicorn-skill 1.0.0 → 1.0.1
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/CHANGELOG.md +25 -0
- package/README.md +48 -12
- package/SKILL.md +87 -256
- package/dist/analyzer/pattern-catalog.d.ts +11 -8
- package/dist/analyzer/pattern-catalog.d.ts.map +1 -1
- package/dist/analyzer/pattern-catalog.js +273 -67
- package/dist/analyzer/pattern-catalog.js.map +1 -1
- package/dist/analyzer/scanner.d.ts +0 -1
- package/dist/analyzer/scanner.d.ts.map +1 -1
- package/dist/analyzer/scanner.js +70 -61
- package/dist/analyzer/scanner.js.map +1 -1
- package/dist/auditor/ux-auditor.d.ts +4 -1
- package/dist/auditor/ux-auditor.d.ts.map +1 -1
- package/dist/auditor/ux-auditor.js +25 -47
- package/dist/auditor/ux-auditor.js.map +1 -1
- package/dist/index.d.ts +40 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -24
- package/dist/index.js.map +1 -1
- package/dist/planner/migration-planner.d.ts +7 -2
- package/dist/planner/migration-planner.d.ts.map +1 -1
- package/dist/planner/migration-planner.js +16 -4
- package/dist/planner/migration-planner.js.map +1 -1
- package/dist/pr-creator/pr-description-builder.js +1 -1
- package/dist/pr-creator/pr-description-builder.js.map +1 -1
- package/dist/scorer/impact-scorer.d.ts +28 -2
- package/dist/scorer/impact-scorer.d.ts.map +1 -1
- package/dist/scorer/impact-scorer.js +46 -111
- package/dist/scorer/impact-scorer.js.map +1 -1
- package/dist/verifier/context7.d.ts +15 -4
- package/dist/verifier/context7.d.ts.map +1 -1
- package/dist/verifier/context7.js +12 -9
- package/dist/verifier/context7.js.map +1 -1
- package/package.json +12 -14
package/dist/analyzer/scanner.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import fsPromises from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { getPatternCatalog } from './pattern-catalog.js';
|
|
4
5
|
const MANIFEST_TYPES = [
|
|
@@ -81,6 +82,11 @@ const MANIFEST_TYPES = [
|
|
|
81
82
|
// ---------------------------------------------------------------------------
|
|
82
83
|
// File-tree walking utilities
|
|
83
84
|
// ---------------------------------------------------------------------------
|
|
85
|
+
/** File extensions that are scannable source code */
|
|
86
|
+
const SOURCE_EXTENSIONS = new Set([
|
|
87
|
+
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
|
|
88
|
+
'.py', '.rs', '.go', '.java', '.sql', '.xml',
|
|
89
|
+
]);
|
|
84
90
|
/** Directories to always skip when walking the file tree */
|
|
85
91
|
const SKIP_DIRS = new Set([
|
|
86
92
|
'node_modules',
|
|
@@ -154,54 +160,6 @@ function matchesFilePattern(filePath, patterns) {
|
|
|
154
160
|
}
|
|
155
161
|
return false;
|
|
156
162
|
}
|
|
157
|
-
// ---------------------------------------------------------------------------
|
|
158
|
-
// Workspace detection
|
|
159
|
-
// ---------------------------------------------------------------------------
|
|
160
|
-
/**
|
|
161
|
-
* Detect workspace roots by scanning for manifest files.
|
|
162
|
-
* For monorepos, each directory containing a manifest is a workspace root.
|
|
163
|
-
*/
|
|
164
|
-
function detectWorkspaces(repoPath) {
|
|
165
|
-
const workspaces = [];
|
|
166
|
-
const visited = new Set();
|
|
167
|
-
for (const filePath of walkDir(repoPath)) {
|
|
168
|
-
const dir = path.dirname(filePath);
|
|
169
|
-
const basename = path.basename(filePath);
|
|
170
|
-
for (const manifest of MANIFEST_TYPES) {
|
|
171
|
-
if (basename === manifest.file && !visited.has(`${dir}:${manifest.file}`)) {
|
|
172
|
-
visited.add(`${dir}:${manifest.file}`);
|
|
173
|
-
let content;
|
|
174
|
-
try {
|
|
175
|
-
content = fs.readFileSync(filePath, 'utf-8');
|
|
176
|
-
}
|
|
177
|
-
catch {
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
// Detect actual package manager from lockfiles
|
|
181
|
-
let packageManager = manifest.packageManager;
|
|
182
|
-
if (manifest.file === 'package.json') {
|
|
183
|
-
packageManager = detectNodePackageManager(dir);
|
|
184
|
-
}
|
|
185
|
-
workspaces.push({
|
|
186
|
-
root: path.relative(repoPath, dir) || '.',
|
|
187
|
-
packageManager,
|
|
188
|
-
language: manifest.language,
|
|
189
|
-
dependencies: manifest.parseDeps(content),
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
// If no workspaces found, create a root workspace from input metadata
|
|
195
|
-
if (workspaces.length === 0) {
|
|
196
|
-
workspaces.push({
|
|
197
|
-
root: '.',
|
|
198
|
-
packageManager: 'unknown',
|
|
199
|
-
language: 'unknown',
|
|
200
|
-
dependencies: {},
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
return workspaces;
|
|
204
|
-
}
|
|
205
163
|
/**
|
|
206
164
|
* Detect the Node.js package manager by checking for lockfiles.
|
|
207
165
|
*/
|
|
@@ -227,12 +185,13 @@ function fileExists(filePath) {
|
|
|
227
185
|
// ---------------------------------------------------------------------------
|
|
228
186
|
/**
|
|
229
187
|
* Scan a single file's content against the pattern catalog.
|
|
188
|
+
* Uses async I/O to avoid blocking the event loop on large repos.
|
|
230
189
|
* Returns detections for each pattern match found.
|
|
231
190
|
*/
|
|
232
|
-
function scanFile(filePath, relativeFilePath, catalog) {
|
|
191
|
+
async function scanFile(filePath, relativeFilePath, catalog) {
|
|
233
192
|
let content;
|
|
234
193
|
try {
|
|
235
|
-
content =
|
|
194
|
+
content = await fsPromises.readFile(filePath, 'utf-8');
|
|
236
195
|
}
|
|
237
196
|
catch {
|
|
238
197
|
// Unreadable file (binary, permissions) — skip
|
|
@@ -250,15 +209,15 @@ function scanFile(filePath, relativeFilePath, catalog) {
|
|
|
250
209
|
for (let i = 0; i < lines.length; i++) {
|
|
251
210
|
const line = lines[i];
|
|
252
211
|
if (line !== undefined && regex.test(line)) {
|
|
253
|
-
// Determine the line range — include surrounding context
|
|
254
|
-
const
|
|
255
|
-
const
|
|
212
|
+
// Determine the line range — include surrounding context (±5 lines)
|
|
213
|
+
const contextRadius = 5;
|
|
214
|
+
const start = Math.max(1, i + 1 - contextRadius); // 1-indexed
|
|
215
|
+
const end = Math.min(lines.length, i + 1 + contextRadius);
|
|
256
216
|
detections.push({
|
|
257
217
|
filePath: relativeFilePath,
|
|
258
218
|
lineRange: { start, end },
|
|
259
219
|
patternCategory: pattern.id,
|
|
260
220
|
confidenceScore: pattern.confidenceBase,
|
|
261
|
-
suggestedLibrary: pattern.suggestedLibrary,
|
|
262
221
|
domain: pattern.domain,
|
|
263
222
|
});
|
|
264
223
|
// Only report the first match per pattern per file to avoid noise
|
|
@@ -288,14 +247,64 @@ export async function scanCodebase(input) {
|
|
|
288
247
|
return { detections: [], workspaces: [] };
|
|
289
248
|
}
|
|
290
249
|
const catalog = getPatternCatalog();
|
|
291
|
-
//
|
|
292
|
-
const workspaces =
|
|
293
|
-
|
|
294
|
-
const
|
|
250
|
+
// ── Single-pass traversal: detect workspaces AND collect source files ──
|
|
251
|
+
const workspaces = [];
|
|
252
|
+
const visitedManifests = new Set();
|
|
253
|
+
const sourceFiles = [];
|
|
295
254
|
for (const filePath of walkDir(repoPath)) {
|
|
296
|
-
const
|
|
297
|
-
const
|
|
298
|
-
|
|
255
|
+
const basename = path.basename(filePath);
|
|
256
|
+
const dir = path.dirname(filePath);
|
|
257
|
+
const ext = path.extname(filePath);
|
|
258
|
+
// Workspace detection: check if this is a manifest file
|
|
259
|
+
for (const manifest of MANIFEST_TYPES) {
|
|
260
|
+
const key = `${dir}:${manifest.file}`;
|
|
261
|
+
if (basename === manifest.file && !visitedManifests.has(key)) {
|
|
262
|
+
visitedManifests.add(key);
|
|
263
|
+
let content;
|
|
264
|
+
try {
|
|
265
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
let packageManager = manifest.packageManager;
|
|
271
|
+
if (manifest.file === 'package.json') {
|
|
272
|
+
packageManager = detectNodePackageManager(dir);
|
|
273
|
+
}
|
|
274
|
+
workspaces.push({
|
|
275
|
+
root: path.relative(repoPath, dir) || '.',
|
|
276
|
+
packageManager,
|
|
277
|
+
language: manifest.language,
|
|
278
|
+
dependencies: manifest.parseDeps(content),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
// Collect source files for scanning
|
|
283
|
+
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
284
|
+
sourceFiles.push({
|
|
285
|
+
filePath,
|
|
286
|
+
relativeFilePath: path.relative(repoPath, filePath),
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Default workspace if none detected
|
|
291
|
+
if (workspaces.length === 0) {
|
|
292
|
+
workspaces.push({
|
|
293
|
+
root: '.',
|
|
294
|
+
packageManager: 'unknown',
|
|
295
|
+
language: 'unknown',
|
|
296
|
+
dependencies: {},
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
// ── Scan source files with async I/O (batched for throughput) ──
|
|
300
|
+
const BATCH_SIZE = 50;
|
|
301
|
+
const detections = [];
|
|
302
|
+
for (let i = 0; i < sourceFiles.length; i += BATCH_SIZE) {
|
|
303
|
+
const batch = sourceFiles.slice(i, i + BATCH_SIZE);
|
|
304
|
+
const batchResults = await Promise.all(batch.map((f) => scanFile(f.filePath, f.relativeFilePath, catalog)));
|
|
305
|
+
for (const result of batchResults) {
|
|
306
|
+
detections.push(...result);
|
|
307
|
+
}
|
|
299
308
|
}
|
|
300
309
|
return { detections, workspaces };
|
|
301
310
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/analyzer/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAA0B,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/analyzer/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ export interface UxAuditItem {
|
|
|
7
7
|
category: UxCategory;
|
|
8
8
|
status: 'present' | 'partial' | 'missing';
|
|
9
9
|
filePaths: string[];
|
|
10
|
+
/** Library recommendation — left undefined by the auditor; filled by AI agent */
|
|
10
11
|
recommendedLibrary?: string;
|
|
11
12
|
rationale: string;
|
|
12
13
|
}
|
|
@@ -16,7 +17,9 @@ export type UxCategory = 'accessibility' | 'error-states' | 'empty-states' | 'lo
|
|
|
16
17
|
* and the project's current library dependencies.
|
|
17
18
|
*
|
|
18
19
|
* Always returns exactly 8 items — one for each UX category.
|
|
19
|
-
*
|
|
20
|
+
* The auditor determines STATUS (present/partial/missing) deterministically.
|
|
21
|
+
* Library recommendations (recommendedLibrary) are NOT filled by the auditor —
|
|
22
|
+
* they are the AI agent's responsibility to fill based on project context.
|
|
20
23
|
*
|
|
21
24
|
* @param scanResult - The result from the codebase scanner
|
|
22
25
|
* @param projectMetadata - Project metadata including current libraries
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ux-auditor.d.ts","sourceRoot":"","sources":["../../src/auditor/ux-auditor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAM9D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,MAAM,UAAU,GAClB,eAAe,GACf,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"ux-auditor.d.ts","sourceRoot":"","sources":["../../src/auditor/ux-auditor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAM9D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,MAAM,UAAU,GAClB,eAAe,GACf,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,yBAAyB,CAAC;AA+P9B;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAAC,GAC9C,aAAa,CA8Bf"}
|
|
@@ -23,10 +23,6 @@ const CATEGORY_CONFIGS = [
|
|
|
23
23
|
'react-focus-lock',
|
|
24
24
|
'@reach/visually-hidden',
|
|
25
25
|
],
|
|
26
|
-
recommendedLibrary: 'react-aria',
|
|
27
|
-
missingRationale: 'No accessibility patterns detected. Add react-aria for accessible primitives with ARIA attributes, focus management, and keyboard navigation built-in.',
|
|
28
|
-
partialRationale: 'Some accessibility patterns found but coverage is incomplete. react-aria provides comprehensive accessible component primitives.',
|
|
29
|
-
presentRationale: 'Accessibility patterns detected across frontend files with proper ARIA attributes and focus management.',
|
|
30
26
|
},
|
|
31
27
|
{
|
|
32
28
|
category: 'error-states',
|
|
@@ -40,10 +36,6 @@ const CATEGORY_CONFIGS = [
|
|
|
40
36
|
'react-query',
|
|
41
37
|
'@tanstack/react-query',
|
|
42
38
|
],
|
|
43
|
-
recommendedLibrary: 'react-error-boundary',
|
|
44
|
-
missingRationale: 'No error boundary or error state patterns detected. react-error-boundary provides declarative error boundaries with fallback UI, retry, and reset capabilities.',
|
|
45
|
-
partialRationale: 'Some error handling found but missing structured error boundaries. react-error-boundary adds declarative fallback UI and recovery patterns.',
|
|
46
|
-
presentRationale: 'Error state handling detected with error boundaries and fallback UI patterns.',
|
|
47
39
|
},
|
|
48
40
|
{
|
|
49
41
|
category: 'empty-states',
|
|
@@ -51,10 +43,6 @@ const CATEGORY_CONFIGS = [
|
|
|
51
43
|
detectionDomains: ['ux-completeness'],
|
|
52
44
|
patternKeywords: [/empty.?state/i, /no.?data/i, /no.?results/i, /placeholder/i, /zero.?state/i],
|
|
53
45
|
libraryIndicators: ['react-empty-state', '@illustrations/undraw'],
|
|
54
|
-
recommendedLibrary: 'react-empty-state',
|
|
55
|
-
missingRationale: 'No empty state patterns detected. Add dedicated empty state components with illustrations and call-to-action buttons for better user guidance.',
|
|
56
|
-
partialRationale: 'Some empty state handling found but not consistently applied. Consider a dedicated empty state component library for consistent UX.',
|
|
57
|
-
presentRationale: 'Empty state patterns detected with appropriate placeholder content and user guidance.',
|
|
58
46
|
},
|
|
59
47
|
{
|
|
60
48
|
category: 'loading-states',
|
|
@@ -68,10 +56,6 @@ const CATEGORY_CONFIGS = [
|
|
|
68
56
|
'@tanstack/react-query',
|
|
69
57
|
'swr',
|
|
70
58
|
],
|
|
71
|
-
recommendedLibrary: 'react-loading-skeleton',
|
|
72
|
-
missingRationale: 'No loading state patterns detected. react-loading-skeleton provides animated placeholder UI that reduces perceived load time and prevents layout shift.',
|
|
73
|
-
partialRationale: 'Hand-rolled loading states found. react-loading-skeleton provides consistent, animated skeleton screens with automatic sizing.',
|
|
74
|
-
presentRationale: 'Loading state patterns detected with skeleton screens or spinner components.',
|
|
75
59
|
},
|
|
76
60
|
{
|
|
77
61
|
category: 'form-validation',
|
|
@@ -86,10 +70,6 @@ const CATEGORY_CONFIGS = [
|
|
|
86
70
|
'@hookform/resolvers',
|
|
87
71
|
'vest',
|
|
88
72
|
],
|
|
89
|
-
recommendedLibrary: 'react-hook-form',
|
|
90
|
-
missingRationale: 'No form validation patterns detected. react-hook-form provides performant form validation with minimal re-renders, schema integration, and accessible error messages.',
|
|
91
|
-
partialRationale: 'Hand-rolled form validation found. react-hook-form reduces boilerplate and provides consistent validation UX with schema-based validation support.',
|
|
92
|
-
presentRationale: 'Form validation patterns detected with structured validation library integration.',
|
|
93
73
|
},
|
|
94
74
|
{
|
|
95
75
|
category: 'performance-feel',
|
|
@@ -113,10 +93,6 @@ const CATEGORY_CONFIGS = [
|
|
|
113
93
|
'react-intersection-observer',
|
|
114
94
|
'framer-motion',
|
|
115
95
|
],
|
|
116
|
-
recommendedLibrary: '@tanstack/react-virtual',
|
|
117
|
-
missingRationale: 'No performance optimization patterns detected. @tanstack/react-virtual provides efficient list virtualization, reducing DOM nodes and improving scroll performance for large datasets.',
|
|
118
|
-
partialRationale: 'Some performance patterns found but missing virtualization or optimistic updates. @tanstack/react-virtual improves rendering performance for large lists.',
|
|
119
|
-
presentRationale: 'Performance optimization patterns detected including virtualization and lazy loading.',
|
|
120
96
|
},
|
|
121
97
|
{
|
|
122
98
|
category: 'copy-consistency',
|
|
@@ -131,10 +107,6 @@ const CATEGORY_CONFIGS = [
|
|
|
131
107
|
'formatjs',
|
|
132
108
|
'@formatjs/intl',
|
|
133
109
|
],
|
|
134
|
-
recommendedLibrary: 'react-i18next',
|
|
135
|
-
missingRationale: 'No internationalization or copy management patterns detected. react-i18next provides structured copy management with pluralization, interpolation, and locale-aware formatting for consistent UI text.',
|
|
136
|
-
partialRationale: 'Hand-rolled i18n patterns found. react-i18next provides centralized copy management ensuring consistency across the application.',
|
|
137
|
-
presentRationale: 'Copy consistency patterns detected with internationalization library integration.',
|
|
138
110
|
},
|
|
139
111
|
{
|
|
140
112
|
category: 'design-system-alignment',
|
|
@@ -164,10 +136,6 @@ const CATEGORY_CONFIGS = [
|
|
|
164
136
|
'@emotion/react',
|
|
165
137
|
'class-variance-authority',
|
|
166
138
|
],
|
|
167
|
-
recommendedLibrary: '@radix-ui/themes',
|
|
168
|
-
missingRationale: 'No design system or component library patterns detected. @radix-ui/themes provides accessible, composable UI primitives that enforce design consistency across the application.',
|
|
169
|
-
partialRationale: 'Some design system patterns found but coverage is incomplete. @radix-ui/themes provides a comprehensive set of accessible, themed components.',
|
|
170
|
-
presentRationale: 'Design system alignment detected with component library and theming patterns.',
|
|
171
139
|
},
|
|
172
140
|
];
|
|
173
141
|
// ---------------------------------------------------------------------------
|
|
@@ -219,6 +187,23 @@ function evaluateCategory(config, detections, currentLibraries) {
|
|
|
219
187
|
return { status: 'missing', filePaths };
|
|
220
188
|
}
|
|
221
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Generate a factual rationale based on the detection status.
|
|
192
|
+
* Does NOT recommend specific libraries — that's the AI agent's job.
|
|
193
|
+
*/
|
|
194
|
+
function generateRationale(category, status, filePaths) {
|
|
195
|
+
const categoryLabel = category.replace(/-/g, ' ');
|
|
196
|
+
if (status === 'present') {
|
|
197
|
+
return `${categoryLabel} patterns detected with library integration.`;
|
|
198
|
+
}
|
|
199
|
+
if (status === 'partial') {
|
|
200
|
+
const fileList = filePaths.length > 0
|
|
201
|
+
? ` in ${filePaths.length} file(s)`
|
|
202
|
+
: '';
|
|
203
|
+
return `Hand-rolled ${categoryLabel} patterns found${fileList}. Consider replacing with a dedicated library.`;
|
|
204
|
+
}
|
|
205
|
+
return `No ${categoryLabel} patterns detected. Manual review recommended.`;
|
|
206
|
+
}
|
|
222
207
|
// ---------------------------------------------------------------------------
|
|
223
208
|
// Public API
|
|
224
209
|
// ---------------------------------------------------------------------------
|
|
@@ -227,7 +212,9 @@ function evaluateCategory(config, detections, currentLibraries) {
|
|
|
227
212
|
* and the project's current library dependencies.
|
|
228
213
|
*
|
|
229
214
|
* Always returns exactly 8 items — one for each UX category.
|
|
230
|
-
*
|
|
215
|
+
* The auditor determines STATUS (present/partial/missing) deterministically.
|
|
216
|
+
* Library recommendations (recommendedLibrary) are NOT filled by the auditor —
|
|
217
|
+
* they are the AI agent's responsibility to fill based on project context.
|
|
231
218
|
*
|
|
232
219
|
* @param scanResult - The result from the codebase scanner
|
|
233
220
|
* @param projectMetadata - Project metadata including current libraries
|
|
@@ -238,21 +225,13 @@ export function auditUxCompleteness(scanResult, projectMetadata) {
|
|
|
238
225
|
const items = [];
|
|
239
226
|
for (const config of CATEGORY_CONFIGS) {
|
|
240
227
|
const { status, filePaths } = evaluateCategory(config, scanResult.detections, currentLibraries);
|
|
241
|
-
|
|
228
|
+
items.push({
|
|
242
229
|
category: config.category,
|
|
243
230
|
status,
|
|
244
231
|
filePaths,
|
|
245
|
-
rationale: status
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
? config.partialRationale
|
|
249
|
-
: config.presentRationale,
|
|
250
|
-
};
|
|
251
|
-
// Add recommendedLibrary for partial or missing statuses (required by spec)
|
|
252
|
-
if (status === 'partial' || status === 'missing') {
|
|
253
|
-
item.recommendedLibrary = config.recommendedLibrary;
|
|
254
|
-
}
|
|
255
|
-
items.push(item);
|
|
232
|
+
rationale: generateRationale(config.category, status, filePaths),
|
|
233
|
+
// recommendedLibrary is intentionally left undefined — AI agent fills it
|
|
234
|
+
});
|
|
256
235
|
}
|
|
257
236
|
// Ensure all 8 categories are present (defensive — should always be true)
|
|
258
237
|
const coveredCategories = new Set(items.map((i) => i.category));
|
|
@@ -262,8 +241,7 @@ export function auditUxCompleteness(scanResult, projectMetadata) {
|
|
|
262
241
|
category,
|
|
263
242
|
status: 'missing',
|
|
264
243
|
filePaths: [],
|
|
265
|
-
|
|
266
|
-
rationale: `No patterns detected for ${category}. Manual review recommended.`,
|
|
244
|
+
rationale: `No ${category.replace(/-/g, ' ')} patterns detected. Manual review recommended.`,
|
|
267
245
|
});
|
|
268
246
|
}
|
|
269
247
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ux-auditor.js","sourceRoot":"","sources":["../../src/auditor/ux-auditor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ux-auditor.js","sourceRoot":"","sources":["../../src/auditor/ux-auditor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Next-Unicorn SKILL — Analyze and Recommend Third-Party Optimizations
|
|
3
3
|
*
|
|
4
|
-
* Scans codebases and
|
|
5
|
-
*
|
|
4
|
+
* Scans codebases and identifies hand-rolled implementations that could be
|
|
5
|
+
* replaced by third-party libraries. Library recommendations are provided
|
|
6
|
+
* by the caller (AI agent or programmatic client) — NOT hardcoded.
|
|
6
7
|
*
|
|
7
8
|
* This is the orchestrator that wires the full pipeline:
|
|
8
|
-
* validate input → scan →
|
|
9
|
-
* vuln scan → auto-update → serialize → PR creation
|
|
9
|
+
* validate input → scan → recommend (caller) → verify → score → plan →
|
|
10
|
+
* audit → filter → vuln scan → auto-update → serialize → PR creation
|
|
10
11
|
*/
|
|
11
12
|
import { OutputSchema } from './schemas/output.schema.js';
|
|
13
|
+
import { type Detection, type ScanResult } from './analyzer/scanner.js';
|
|
12
14
|
import { type Context7Client } from './verifier/context7.js';
|
|
13
15
|
import { type ExclusionRecord } from './utils/constraint-filter.js';
|
|
14
16
|
import { type PeerDependencyResolver } from './checker/peer-dependency-checker.js';
|
|
@@ -16,12 +18,38 @@ import type { VulnerabilityClient } from './security/osv-client.js';
|
|
|
16
18
|
import type { RegistryClient } from './updater/registry-client.js';
|
|
17
19
|
import type { PlatformClient } from './pr-creator/platform-client.js';
|
|
18
20
|
import type { GitOperations } from './pr-creator/git-operations.js';
|
|
19
|
-
export declare const VERSION = "
|
|
21
|
+
export declare const VERSION = "1.0.1";
|
|
22
|
+
/**
|
|
23
|
+
* A library recommendation provided by the AI agent (or caller).
|
|
24
|
+
* The scanner detects WHAT is hand-rolled; the recommender decides WHAT to use.
|
|
25
|
+
*/
|
|
26
|
+
export interface LibraryRecommendation {
|
|
27
|
+
/** Library name (e.g., "zustand", "@tanstack/react-query") */
|
|
28
|
+
library: string;
|
|
29
|
+
/** Version constraint (e.g., "^5.0.0") */
|
|
30
|
+
version: string;
|
|
31
|
+
/** SPDX license identifier (e.g., "MIT") */
|
|
32
|
+
license: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Function that provides library recommendations for detections.
|
|
36
|
+
* Called once per detection. Return null to skip a detection (no recommendation).
|
|
37
|
+
*
|
|
38
|
+
* In AI agent mode: the agent fills this based on its knowledge + Context7.
|
|
39
|
+
* In programmatic/test mode: the caller provides a deterministic function.
|
|
40
|
+
*/
|
|
41
|
+
export type Recommender = (detection: Detection) => LibraryRecommendation | null;
|
|
20
42
|
export interface AnalyzeOptions {
|
|
21
43
|
/** Raw input to be validated against InputSchema */
|
|
22
44
|
input: unknown;
|
|
23
45
|
/** Injected Context7 client for testability — no real HTTP calls in tests */
|
|
24
46
|
context7Client: Context7Client;
|
|
47
|
+
/**
|
|
48
|
+
* Recommender function: maps each detection to a library recommendation.
|
|
49
|
+
* This is the key integration point for AI agents — the agent decides
|
|
50
|
+
* which library best fits each detected pattern based on project context.
|
|
51
|
+
*/
|
|
52
|
+
recommender: Recommender;
|
|
25
53
|
/** Optional — if provided, enables vulnerability scanning */
|
|
26
54
|
vulnClient?: VulnerabilityClient;
|
|
27
55
|
/** Optional — if provided, enables auto-update recommendations */
|
|
@@ -36,6 +64,8 @@ export interface AnalyzeOptions {
|
|
|
36
64
|
export type AnalyzeResult = {
|
|
37
65
|
success: true;
|
|
38
66
|
output: OutputSchema;
|
|
67
|
+
/** Raw scan result (detections + workspaces) for AI agent further analysis */
|
|
68
|
+
scanResult: ScanResult;
|
|
39
69
|
json: string;
|
|
40
70
|
prettyJson: string;
|
|
41
71
|
exclusions: ExclusionRecord[];
|
|
@@ -48,18 +78,22 @@ export type { Context7Client, VerificationResult } from './verifier/context7.js'
|
|
|
48
78
|
export type { ExclusionRecord } from './utils/constraint-filter.js';
|
|
49
79
|
export type { InputSchema } from './schemas/input.schema.js';
|
|
50
80
|
export type { OutputSchema } from './schemas/output.schema.js';
|
|
81
|
+
export type { Detection, ScanResult } from './analyzer/scanner.js';
|
|
51
82
|
export type { VulnerabilityClient } from './security/osv-client.js';
|
|
52
83
|
export type { RegistryClient } from './updater/registry-client.js';
|
|
53
84
|
export type { PlatformClient } from './pr-creator/platform-client.js';
|
|
54
85
|
export type { GitOperations } from './pr-creator/git-operations.js';
|
|
55
86
|
export type { PeerDependencyResolver } from './checker/peer-dependency-checker.js';
|
|
87
|
+
export { scanCodebase } from './analyzer/scanner.js';
|
|
88
|
+
export { getPatternCatalog } from './analyzer/pattern-catalog.js';
|
|
56
89
|
/**
|
|
57
90
|
* Run the full Next-Unicorn analysis pipeline.
|
|
58
91
|
*
|
|
59
92
|
* Pipeline steps:
|
|
60
93
|
* 1. Validate input with InputSchema Zod schema
|
|
61
94
|
* 2. Scan codebase with scanCodebase
|
|
62
|
-
*
|
|
95
|
+
* 2.5 Get library recommendations from the recommender (AI agent / caller)
|
|
96
|
+
* 3. Verify recommendations with Context7
|
|
63
97
|
* 4. Score each detection
|
|
64
98
|
* 5. Build RecommendedChange objects
|
|
65
99
|
* 6. Apply dependency conflict detection
|
|
@@ -71,8 +105,6 @@ export type { PeerDependencyResolver } from './checker/peer-dependency-checker.j
|
|
|
71
105
|
* 11. Assemble OutputSchema, serialize
|
|
72
106
|
* 12. PR auto-creation (optional — Phase 2)
|
|
73
107
|
* 13. Return result
|
|
74
|
-
*
|
|
75
|
-
* Requirements: 1.1, 7.3, 10.*, 11.*, 12.*
|
|
76
108
|
*/
|
|
77
109
|
export declare function analyze(options: AnalyzeOptions): Promise<AnalyzeResult>;
|
|
78
110
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|