@aiready/core 0.24.23 → 0.24.26
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/dist/chunk-3GCIM6XG.mjs +904 -0
- package/dist/chunk-3S5WU6KX.mjs +552 -0
- package/dist/chunk-4OMXBYX7.mjs +167 -0
- package/dist/chunk-6YWGFKZG.mjs +250 -0
- package/dist/chunk-A3BIROBZ.mjs +902 -0
- package/dist/chunk-BYMQDORS.mjs +256 -0
- package/dist/chunk-CBZNRNEF.mjs +309 -0
- package/dist/chunk-ET2WRQSM.mjs +262 -0
- package/dist/chunk-F4FTHFHK.mjs +552 -0
- package/dist/chunk-G737F72Q.mjs +256 -0
- package/dist/chunk-GVFUAIWU.mjs +864 -0
- package/dist/chunk-KSEA5XDH.mjs +894 -0
- package/dist/chunk-LMIZRJFV.mjs +256 -0
- package/dist/chunk-LRPBPWBM.mjs +170 -0
- package/dist/chunk-MOTBXU6W.mjs +902 -0
- package/dist/chunk-OAH6FVVF.mjs +919 -0
- package/dist/chunk-OCM6HLBM.mjs +262 -0
- package/dist/chunk-OFBRNGKT.mjs +893 -0
- package/dist/chunk-P3KYGPO4.mjs +262 -0
- package/dist/chunk-PNWSO6XQ.mjs +250 -0
- package/dist/chunk-SO6UKAPR.mjs +164 -0
- package/dist/chunk-T2FW6AAF.mjs +552 -0
- package/dist/chunk-TQX77RIC.mjs +250 -0
- package/dist/chunk-X64EJ3ZO.mjs +314 -0
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +32 -5
- package/dist/client/index.mjs +1 -1
- package/dist/csharp-parser-3CGM6FKB.mjs +9 -0
- package/dist/csharp-parser-UWRUYHUH.mjs +9 -0
- package/dist/csharp-parser-WIAIE3DD.mjs +9 -0
- package/dist/go-parser-AH5QNS4O.mjs +9 -0
- package/dist/go-parser-CSAB23BL.mjs +9 -0
- package/dist/go-parser-Q3HI32B7.mjs +9 -0
- package/dist/index-CL_0jxiJ.d.mts +1315 -0
- package/dist/index-CL_0jxiJ.d.ts +1315 -0
- package/dist/index-ClwnZa_Y.d.mts +1333 -0
- package/dist/index-ClwnZa_Y.d.ts +1333 -0
- package/dist/index-DC0cdf0g.d.mts +1321 -0
- package/dist/index-DC0cdf0g.d.ts +1321 -0
- package/dist/index-DKqKGhcJ.d.mts +1309 -0
- package/dist/index-DKqKGhcJ.d.ts +1309 -0
- package/dist/index-DNnlhdk0.d.mts +1318 -0
- package/dist/index-DNnlhdk0.d.ts +1318 -0
- package/dist/index-De2xy_k5.d.mts +1326 -0
- package/dist/index-De2xy_k5.d.ts +1326 -0
- package/dist/index.d.mts +104 -20
- package/dist/index.d.ts +104 -20
- package/dist/index.js +581 -147
- package/dist/index.mjs +507 -134
- package/dist/java-parser-GUKWCEYS.mjs +9 -0
- package/dist/java-parser-XTWT5Y5I.mjs +9 -0
- package/dist/java-parser-YP5XWLQK.mjs +9 -0
- package/dist/python-parser-AOPXUEIV.mjs +8 -0
- package/dist/python-parser-FB55P6UA.mjs +8 -0
- package/dist/python-parser-WIJPSRKC.mjs +8 -0
- package/dist/typescript-parser-5ZWLLMWJ.mjs +7 -0
- package/dist/typescript-parser-TWPRLYK6.mjs +7 -0
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -96,7 +96,10 @@ var init_typescript_parser = __esm({
|
|
|
96
96
|
range: true,
|
|
97
97
|
tokens: true,
|
|
98
98
|
comment: true,
|
|
99
|
-
jsx: filePath.endsWith("x")
|
|
99
|
+
jsx: filePath.endsWith("x"),
|
|
100
|
+
ecmaVersion: "latest"
|
|
101
|
+
// Support for latest TypeScript features like Decorators and Explicit Resource Management
|
|
102
|
+
// are enabled by default in latest typescript-estree when ecmaVersion is 'latest'.
|
|
100
103
|
});
|
|
101
104
|
} catch (error) {
|
|
102
105
|
const err = error;
|
|
@@ -114,7 +117,10 @@ var init_typescript_parser = __esm({
|
|
|
114
117
|
range: true,
|
|
115
118
|
tokens: true,
|
|
116
119
|
comment: true,
|
|
117
|
-
jsx: filePath.endsWith("x")
|
|
120
|
+
jsx: filePath.endsWith("x"),
|
|
121
|
+
ecmaVersion: "latest"
|
|
122
|
+
// Support for latest TypeScript features like Decorators and Explicit Resource Management
|
|
123
|
+
// are enabled by default in latest typescript-estree when ecmaVersion is 'latest'.
|
|
118
124
|
});
|
|
119
125
|
const imports = this.extractImports(ast);
|
|
120
126
|
const exports2 = this.extractExports(ast, code, filePath);
|
|
@@ -266,7 +272,7 @@ var init_typescript_parser = __esm({
|
|
|
266
272
|
let isPrimitive = false;
|
|
267
273
|
let isTyped = false;
|
|
268
274
|
if (initializer) {
|
|
269
|
-
if (initializer.type === "Literal" || initializer.type === "TemplateLiteral" && initializer.expressions.length === 0) {
|
|
275
|
+
if (initializer.type === "Literal" || initializer.type === "BigIntLiteral" || initializer.type === "TemplateLiteral" && initializer.expressions.length === 0) {
|
|
270
276
|
isPrimitive = true;
|
|
271
277
|
}
|
|
272
278
|
}
|
|
@@ -365,7 +371,8 @@ var init_typescript_parser = __esm({
|
|
|
365
371
|
body,
|
|
366
372
|
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
367
373
|
);
|
|
368
|
-
if (bodyContent.includes('"name":"console"') || bodyContent.includes('"name":"process"') || bodyContent.includes('"name":"fs"') || bodyContent.includes('"name":"global"') || bodyContent.includes('"name":"window"') || bodyContent.includes('"name":"fetch"') || bodyContent.includes('"name":"axios"'))
|
|
374
|
+
if (bodyContent.includes('"name":"console"') || bodyContent.includes('"name":"process"') || bodyContent.includes('"name":"fs"') || bodyContent.includes('"name":"global"') || bodyContent.includes('"name":"window"') || bodyContent.includes('"name":"fetch"') || bodyContent.includes('"name":"axios"') || bodyContent.includes('"type":"UsingDeclaration"') || // Explicit Resource Management
|
|
375
|
+
bodyContent.includes('"type":"AwaitExpression"')) {
|
|
369
376
|
return false;
|
|
370
377
|
}
|
|
371
378
|
return true;
|
|
@@ -501,6 +508,25 @@ var init_metadata_utils = __esm({
|
|
|
501
508
|
}
|
|
502
509
|
});
|
|
503
510
|
|
|
511
|
+
// src/utils/path-utils.ts
|
|
512
|
+
function getDirname(importMetaUrl) {
|
|
513
|
+
if (importMetaUrl) {
|
|
514
|
+
return (0, import_path4.dirname)((0, import_url.fileURLToPath)(importMetaUrl));
|
|
515
|
+
}
|
|
516
|
+
if (typeof __dirname !== "undefined") {
|
|
517
|
+
return __dirname;
|
|
518
|
+
}
|
|
519
|
+
throw new Error("getDirname: importMetaUrl is required in ESM environments");
|
|
520
|
+
}
|
|
521
|
+
var import_path4, import_url;
|
|
522
|
+
var init_path_utils = __esm({
|
|
523
|
+
"src/utils/path-utils.ts"() {
|
|
524
|
+
"use strict";
|
|
525
|
+
import_path4 = require("path");
|
|
526
|
+
import_url = require("url");
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
|
|
504
530
|
// src/parsers/tree-sitter-utils.ts
|
|
505
531
|
async function initTreeSitter() {
|
|
506
532
|
if (isTreeSitterInitialized) return;
|
|
@@ -554,18 +580,18 @@ function getWasmPath(language) {
|
|
|
554
580
|
const wasmFileName = language === "web-tree-sitter" ? "web-tree-sitter.wasm" : `tree-sitter-${language}.wasm`;
|
|
555
581
|
const immediatePaths = [
|
|
556
582
|
path.join(process.cwd(), wasmFileName),
|
|
557
|
-
path.join(
|
|
558
|
-
path.join(
|
|
583
|
+
path.join(__dirname2, wasmFileName),
|
|
584
|
+
path.join(__dirname2, "assets", wasmFileName)
|
|
559
585
|
];
|
|
560
586
|
for (const p of immediatePaths) {
|
|
561
587
|
if (fs.existsSync(p)) return p;
|
|
562
588
|
}
|
|
563
|
-
const pnpmPath = findInPnpmStore(
|
|
589
|
+
const pnpmPath = findInPnpmStore(__dirname2, wasmFileName);
|
|
564
590
|
if (pnpmPath) return pnpmPath;
|
|
565
591
|
const pnpmPathCwd = findInPnpmStore(process.cwd(), wasmFileName);
|
|
566
592
|
if (pnpmPathCwd) return pnpmPathCwd;
|
|
567
593
|
console.warn(
|
|
568
|
-
`[Parser] WASM file for ${language} not found. CWD: ${process.cwd()}, DIR: ${
|
|
594
|
+
`[Parser] WASM file for ${language} not found. CWD: ${process.cwd()}, DIR: ${__dirname2}`
|
|
569
595
|
);
|
|
570
596
|
return null;
|
|
571
597
|
}
|
|
@@ -584,24 +610,23 @@ async function setupParser(language) {
|
|
|
584
610
|
return null;
|
|
585
611
|
}
|
|
586
612
|
}
|
|
587
|
-
var Parser, path, fs,
|
|
613
|
+
var Parser, path, fs, import_meta, getDirname2, __dirname2, isTreeSitterInitialized;
|
|
588
614
|
var init_tree_sitter_utils = __esm({
|
|
589
615
|
"src/parsers/tree-sitter-utils.ts"() {
|
|
590
616
|
"use strict";
|
|
591
617
|
Parser = __toESM(require("web-tree-sitter"));
|
|
592
618
|
path = __toESM(require("path"));
|
|
593
619
|
fs = __toESM(require("fs"));
|
|
594
|
-
|
|
620
|
+
init_path_utils();
|
|
595
621
|
import_meta = {};
|
|
596
|
-
|
|
622
|
+
getDirname2 = () => {
|
|
597
623
|
try {
|
|
598
|
-
|
|
599
|
-
return path.dirname((0, import_url.fileURLToPath)(import_meta.url));
|
|
624
|
+
return getDirname(import_meta.url);
|
|
600
625
|
} catch {
|
|
601
626
|
return process.cwd();
|
|
602
627
|
}
|
|
603
628
|
};
|
|
604
|
-
|
|
629
|
+
__dirname2 = getDirname2();
|
|
605
630
|
isTreeSitterInitialized = false;
|
|
606
631
|
}
|
|
607
632
|
});
|
|
@@ -2034,6 +2059,7 @@ __export(index_exports, {
|
|
|
2034
2059
|
COMMON_FINE_TUNING_OPTIONS: () => COMMON_FINE_TUNING_OPTIONS,
|
|
2035
2060
|
CONTEXT_TIER_THRESHOLDS: () => CONTEXT_TIER_THRESHOLDS,
|
|
2036
2061
|
CSharpParser: () => CSharpParser,
|
|
2062
|
+
DEFAULT_AUTO_EXCLUDE_PATTERNS: () => DEFAULT_AUTO_EXCLUDE_PATTERNS,
|
|
2037
2063
|
DEFAULT_COST_CONFIG: () => DEFAULT_COST_CONFIG,
|
|
2038
2064
|
DEFAULT_EXCLUDE: () => DEFAULT_EXCLUDE,
|
|
2039
2065
|
DEFAULT_TOOL_WEIGHTS: () => DEFAULT_TOOL_WEIGHTS,
|
|
@@ -2042,6 +2068,8 @@ __export(index_exports, {
|
|
|
2042
2068
|
FRIENDLY_TOOL_NAMES: () => FRIENDLY_TOOL_NAMES,
|
|
2043
2069
|
GLOBAL_INFRA_OPTIONS: () => GLOBAL_INFRA_OPTIONS,
|
|
2044
2070
|
GLOBAL_SCAN_OPTIONS: () => GLOBAL_SCAN_OPTIONS,
|
|
2071
|
+
GitHubIssueResolverAgent: () => GitHubIssueResolverAgent,
|
|
2072
|
+
GitHubService: () => GitHubService,
|
|
2045
2073
|
GoParser: () => GoParser,
|
|
2046
2074
|
IssueSchema: () => IssueSchema,
|
|
2047
2075
|
IssueType: () => IssueType,
|
|
@@ -2146,6 +2174,8 @@ __export(index_exports, {
|
|
|
2146
2174
|
generateStatCards: () => generateStatCards,
|
|
2147
2175
|
generateTable: () => generateTable,
|
|
2148
2176
|
generateValueChain: () => generateValueChain,
|
|
2177
|
+
getChangedFiles: () => getChangedFiles,
|
|
2178
|
+
getDirname: () => getDirname,
|
|
2149
2179
|
getElapsedTime: () => getElapsedTime,
|
|
2150
2180
|
getErrorMessage: () => getErrorMessage,
|
|
2151
2181
|
getFileCommitTimestamps: () => getFileCommitTimestamps,
|
|
@@ -2214,12 +2244,14 @@ __export(index_exports, {
|
|
|
2214
2244
|
resolveOutputPath: () => resolveOutputPath,
|
|
2215
2245
|
runBatchAnalysis: () => runBatchAnalysis,
|
|
2216
2246
|
runStandardCliAction: () => runStandardCliAction,
|
|
2247
|
+
safeJsonStringify: () => safeJsonStringify,
|
|
2217
2248
|
saveScoreEntry: () => saveScoreEntry,
|
|
2218
2249
|
scanEntries: () => scanEntries,
|
|
2219
2250
|
scanFiles: () => scanFiles,
|
|
2220
2251
|
setupParser: () => setupParser,
|
|
2221
2252
|
severityToAnnotationLevel: () => severityToAnnotationLevel,
|
|
2222
2253
|
toErrorMessage: () => toErrorMessage,
|
|
2254
|
+
validateConfig: () => validateConfig,
|
|
2223
2255
|
validateSpokeOutput: () => validateSpokeOutput,
|
|
2224
2256
|
validateWithSchema: () => validateWithSchema,
|
|
2225
2257
|
withErrorHandling: () => withErrorHandling,
|
|
@@ -2325,6 +2357,7 @@ var import_zod3 = require("zod");
|
|
|
2325
2357
|
var IssueSchema = import_zod3.z.object({
|
|
2326
2358
|
type: IssueTypeSchema,
|
|
2327
2359
|
severity: SeveritySchema,
|
|
2360
|
+
category: import_zod3.z.string().optional(),
|
|
2328
2361
|
message: import_zod3.z.string(),
|
|
2329
2362
|
location: LocationSchema,
|
|
2330
2363
|
suggestion: import_zod3.z.string().optional()
|
|
@@ -2365,6 +2398,7 @@ var SpokeSummarySchema = import_zod5.z.object({
|
|
|
2365
2398
|
totalIssues: import_zod5.z.number().optional(),
|
|
2366
2399
|
criticalIssues: import_zod5.z.number().optional(),
|
|
2367
2400
|
majorIssues: import_zod5.z.number().optional(),
|
|
2401
|
+
minorIssues: import_zod5.z.number().optional(),
|
|
2368
2402
|
score: import_zod5.z.number().optional()
|
|
2369
2403
|
}).catchall(import_zod5.z.any());
|
|
2370
2404
|
var SpokeOutputSchema = import_zod5.z.object({
|
|
@@ -2383,6 +2417,7 @@ var UnifiedReportSchema = import_zod5.z.object({
|
|
|
2383
2417
|
totalIssues: import_zod5.z.number(),
|
|
2384
2418
|
criticalIssues: import_zod5.z.number(),
|
|
2385
2419
|
majorIssues: import_zod5.z.number(),
|
|
2420
|
+
minorIssues: import_zod5.z.number(),
|
|
2386
2421
|
businessImpact: import_zod5.z.object({
|
|
2387
2422
|
estimatedMonthlyWaste: import_zod5.z.number().optional(),
|
|
2388
2423
|
potentialSavings: import_zod5.z.number().optional(),
|
|
@@ -2405,9 +2440,24 @@ var UnifiedReportSchema = import_zod5.z.object({
|
|
|
2405
2440
|
|
|
2406
2441
|
// src/types/schemas/config.ts
|
|
2407
2442
|
var import_zod6 = require("zod");
|
|
2443
|
+
var AutoExcludeSchema = import_zod6.z.object({
|
|
2444
|
+
/** Enable automatic detection of test files */
|
|
2445
|
+
tests: import_zod6.z.boolean().optional(),
|
|
2446
|
+
/** Enable automatic detection of mock files */
|
|
2447
|
+
mocks: import_zod6.z.boolean().optional(),
|
|
2448
|
+
/** Enable automatic detection of barrel/re-export files */
|
|
2449
|
+
barrels: import_zod6.z.boolean().optional(),
|
|
2450
|
+
/** Enable automatic detection of generated files */
|
|
2451
|
+
generated: import_zod6.z.boolean().optional()
|
|
2452
|
+
}).optional();
|
|
2453
|
+
var TieredExcludeSchema = import_zod6.z.record(import_zod6.z.string(), import_zod6.z.array(import_zod6.z.string()));
|
|
2408
2454
|
var AIReadyConfigSchema = import_zod6.z.object({
|
|
2409
|
-
/**
|
|
2410
|
-
|
|
2455
|
+
/** Extend from another config file (relative path) */
|
|
2456
|
+
extends: import_zod6.z.string().optional(),
|
|
2457
|
+
/** Files or directories to exclude from scan (flat array or tiered) */
|
|
2458
|
+
exclude: import_zod6.z.union([import_zod6.z.array(import_zod6.z.string()), TieredExcludeSchema]).optional(),
|
|
2459
|
+
/** Auto-exclusion settings for common patterns */
|
|
2460
|
+
autoExclude: AutoExcludeSchema,
|
|
2411
2461
|
/** Fail CI/CD if score below threshold (0-100) */
|
|
2412
2462
|
threshold: import_zod6.z.number().optional(),
|
|
2413
2463
|
/** Fail on issues: critical, major, any */
|
|
@@ -2434,7 +2484,15 @@ var AIReadyConfigSchema = import_zod6.z.object({
|
|
|
2434
2484
|
compareBaseline: import_zod6.z.string().optional()
|
|
2435
2485
|
}).optional(),
|
|
2436
2486
|
/** Tool-specific configuration overrides (Strictly ToolName -> Config) */
|
|
2437
|
-
tools: import_zod6.z.record(
|
|
2487
|
+
tools: import_zod6.z.record(
|
|
2488
|
+
import_zod6.z.string(),
|
|
2489
|
+
import_zod6.z.object({
|
|
2490
|
+
/** Whether to enable this tool */
|
|
2491
|
+
enabled: import_zod6.z.boolean().optional(),
|
|
2492
|
+
/** Severity overrides for specific categories */
|
|
2493
|
+
severityOverrides: import_zod6.z.record(import_zod6.z.string(), SeveritySchema).optional()
|
|
2494
|
+
}).catchall(import_zod6.z.any())
|
|
2495
|
+
).optional(),
|
|
2438
2496
|
/** Scoring profile and weights */
|
|
2439
2497
|
scoring: import_zod6.z.object({
|
|
2440
2498
|
/** Name of the scoring profile (e.g. "strict", "balanced") */
|
|
@@ -2516,7 +2574,8 @@ var GLOBAL_INFRA_OPTIONS = [
|
|
|
2516
2574
|
"include",
|
|
2517
2575
|
"exclude",
|
|
2518
2576
|
"tools",
|
|
2519
|
-
"scoring"
|
|
2577
|
+
"scoring",
|
|
2578
|
+
"changedFilesOnly"
|
|
2520
2579
|
];
|
|
2521
2580
|
var GLOBAL_SCAN_OPTIONS = [
|
|
2522
2581
|
"rootDir",
|
|
@@ -2527,7 +2586,7 @@ var GLOBAL_SCAN_OPTIONS = [
|
|
|
2527
2586
|
"output",
|
|
2528
2587
|
"format",
|
|
2529
2588
|
"parallel",
|
|
2530
|
-
"
|
|
2589
|
+
"changedFilesOnly"
|
|
2531
2590
|
];
|
|
2532
2591
|
var COMMON_FINE_TUNING_OPTIONS = [
|
|
2533
2592
|
"maxDepth",
|
|
@@ -2795,6 +2854,106 @@ var import_promises = require("fs/promises");
|
|
|
2795
2854
|
var import_fs = require("fs");
|
|
2796
2855
|
var import_path = require("path");
|
|
2797
2856
|
var import_ignore = __toESM(require("ignore"));
|
|
2857
|
+
|
|
2858
|
+
// src/utils/history-git.ts
|
|
2859
|
+
var import_child_process = require("child_process");
|
|
2860
|
+
function getFileCommitTimestamps(file) {
|
|
2861
|
+
const lineStamps = {};
|
|
2862
|
+
try {
|
|
2863
|
+
const output = (0, import_child_process.execSync)(`git blame -t "${file}"`, {
|
|
2864
|
+
encoding: "utf-8",
|
|
2865
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2866
|
+
});
|
|
2867
|
+
const lines = output.split("\n");
|
|
2868
|
+
for (const line of lines) {
|
|
2869
|
+
if (!line) continue;
|
|
2870
|
+
const match = line.match(/^\S+\s+\(.*?(\d{10,})\s+[-+]\d+\s+(\d+)\)/);
|
|
2871
|
+
if (match) {
|
|
2872
|
+
const ts = parseInt(match[1], 10);
|
|
2873
|
+
const ln = parseInt(match[2], 10);
|
|
2874
|
+
lineStamps[ln] = ts;
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
} catch {
|
|
2878
|
+
}
|
|
2879
|
+
return lineStamps;
|
|
2880
|
+
}
|
|
2881
|
+
function getLineRangeLastModifiedCached(lineStamps, startLine, endLine) {
|
|
2882
|
+
let latest = 0;
|
|
2883
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
2884
|
+
if (lineStamps[i] && lineStamps[i] > latest) {
|
|
2885
|
+
latest = lineStamps[i];
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
return latest;
|
|
2889
|
+
}
|
|
2890
|
+
function getRepoMetadata(directory) {
|
|
2891
|
+
const metadata = {};
|
|
2892
|
+
try {
|
|
2893
|
+
try {
|
|
2894
|
+
metadata.url = (0, import_child_process.execSync)("git config --get remote.origin.url", {
|
|
2895
|
+
cwd: directory,
|
|
2896
|
+
encoding: "utf-8",
|
|
2897
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2898
|
+
}).trim();
|
|
2899
|
+
} catch {
|
|
2900
|
+
}
|
|
2901
|
+
try {
|
|
2902
|
+
metadata.branch = (0, import_child_process.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
2903
|
+
cwd: directory,
|
|
2904
|
+
encoding: "utf-8",
|
|
2905
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2906
|
+
}).trim();
|
|
2907
|
+
} catch {
|
|
2908
|
+
}
|
|
2909
|
+
try {
|
|
2910
|
+
metadata.commit = (0, import_child_process.execSync)("git rev-parse HEAD", {
|
|
2911
|
+
cwd: directory,
|
|
2912
|
+
encoding: "utf-8",
|
|
2913
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2914
|
+
}).trim();
|
|
2915
|
+
} catch {
|
|
2916
|
+
}
|
|
2917
|
+
try {
|
|
2918
|
+
metadata.author = (0, import_child_process.execSync)("git log -1 --format=%ae", {
|
|
2919
|
+
cwd: directory,
|
|
2920
|
+
encoding: "utf-8",
|
|
2921
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2922
|
+
}).trim();
|
|
2923
|
+
} catch {
|
|
2924
|
+
}
|
|
2925
|
+
} catch {
|
|
2926
|
+
}
|
|
2927
|
+
return metadata;
|
|
2928
|
+
}
|
|
2929
|
+
function getChangedFiles(directory) {
|
|
2930
|
+
const changedFiles = /* @__PURE__ */ new Set();
|
|
2931
|
+
try {
|
|
2932
|
+
const trackedOutput = (0, import_child_process.execSync)("git diff HEAD --name-only", {
|
|
2933
|
+
cwd: directory,
|
|
2934
|
+
encoding: "utf-8",
|
|
2935
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2936
|
+
}).trim();
|
|
2937
|
+
if (trackedOutput) {
|
|
2938
|
+
trackedOutput.split("\n").forEach((f) => changedFiles.add(f));
|
|
2939
|
+
}
|
|
2940
|
+
const untrackedOutput = (0, import_child_process.execSync)(
|
|
2941
|
+
"git ls-files --others --exclude-standard",
|
|
2942
|
+
{
|
|
2943
|
+
cwd: directory,
|
|
2944
|
+
encoding: "utf-8",
|
|
2945
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2946
|
+
}
|
|
2947
|
+
).trim();
|
|
2948
|
+
if (untrackedOutput) {
|
|
2949
|
+
untrackedOutput.split("\n").forEach((f) => changedFiles.add(f));
|
|
2950
|
+
}
|
|
2951
|
+
} catch {
|
|
2952
|
+
}
|
|
2953
|
+
return Array.from(changedFiles);
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
// src/utils/file-scanner.ts
|
|
2798
2957
|
var DEFAULT_EXCLUDE = [
|
|
2799
2958
|
// Dependencies
|
|
2800
2959
|
"**/node_modules/**",
|
|
@@ -2866,12 +3025,12 @@ var VAGUE_FILE_NAMES = /* @__PURE__ */ new Set([
|
|
|
2866
3025
|
]);
|
|
2867
3026
|
async function scanFiles(options) {
|
|
2868
3027
|
const {
|
|
2869
|
-
rootDir,
|
|
3028
|
+
rootDir = ".",
|
|
2870
3029
|
include = ["**/*.{ts,tsx,js,jsx,py,java,go,rs,cs}"],
|
|
2871
3030
|
// Multi-language support
|
|
2872
3031
|
exclude
|
|
2873
3032
|
} = options;
|
|
2874
|
-
const ignoreFilePath = (0, import_path.join)(rootDir
|
|
3033
|
+
const ignoreFilePath = (0, import_path.join)(rootDir, ".aireadyignore");
|
|
2875
3034
|
let ignoreFromFile = [];
|
|
2876
3035
|
if ((0, import_fs.existsSync)(ignoreFilePath)) {
|
|
2877
3036
|
try {
|
|
@@ -2904,13 +3063,14 @@ async function scanFiles(options) {
|
|
|
2904
3063
|
// Minimal ignore for gitignore discovery
|
|
2905
3064
|
absolute: true
|
|
2906
3065
|
});
|
|
3066
|
+
let filtered = files;
|
|
2907
3067
|
if (gitignoreFiles.length > 0) {
|
|
2908
3068
|
try {
|
|
2909
3069
|
const ig = (0, import_ignore.default)();
|
|
2910
3070
|
for (const gitignorePath of gitignoreFiles) {
|
|
2911
3071
|
const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
|
|
2912
3072
|
const gitignoreDir = (0, import_path.dirname)(gitignorePath);
|
|
2913
|
-
const relativePrefix = (0, import_path.relative)(rootDir
|
|
3073
|
+
const relativePrefix = (0, import_path.relative)(rootDir, gitignoreDir).replace(
|
|
2914
3074
|
/\\/g,
|
|
2915
3075
|
"/"
|
|
2916
3076
|
);
|
|
@@ -2925,22 +3085,26 @@ async function scanFiles(options) {
|
|
|
2925
3085
|
);
|
|
2926
3086
|
}
|
|
2927
3087
|
}
|
|
2928
|
-
|
|
2929
|
-
let rel = (0, import_path.relative)(rootDir
|
|
3088
|
+
filtered = files.filter((f) => {
|
|
3089
|
+
let rel = (0, import_path.relative)(rootDir, f).replace(/\\/g, "/");
|
|
2930
3090
|
if (rel === "") rel = f;
|
|
2931
3091
|
return !ig.ignores(rel);
|
|
2932
3092
|
});
|
|
2933
|
-
return filtered;
|
|
2934
3093
|
} catch {
|
|
2935
|
-
return files;
|
|
2936
3094
|
}
|
|
2937
3095
|
}
|
|
2938
|
-
|
|
3096
|
+
if (options.changedFilesOnly) {
|
|
3097
|
+
const changedFiles = getChangedFiles(rootDir).map(
|
|
3098
|
+
(f) => (0, import_path.resolve)(rootDir, f)
|
|
3099
|
+
);
|
|
3100
|
+
return filtered.filter((f) => changedFiles.includes(f));
|
|
3101
|
+
}
|
|
3102
|
+
return filtered;
|
|
2939
3103
|
}
|
|
2940
3104
|
async function scanEntries(options) {
|
|
2941
3105
|
const files = await scanFiles(options);
|
|
2942
|
-
const { rootDir, exclude, includeTests } = options;
|
|
2943
|
-
const ignoreFilePath = (0, import_path.join)(rootDir
|
|
3106
|
+
const { rootDir = ".", exclude, includeTests } = options;
|
|
3107
|
+
const ignoreFilePath = (0, import_path.join)(rootDir, ".aireadyignore");
|
|
2944
3108
|
let ignoreFromFile = [];
|
|
2945
3109
|
if ((0, import_fs.existsSync)(ignoreFilePath)) {
|
|
2946
3110
|
try {
|
|
@@ -2976,7 +3140,7 @@ async function scanEntries(options) {
|
|
|
2976
3140
|
for (const gitignorePath of gitignoreFiles) {
|
|
2977
3141
|
const gitTxt = await (0, import_promises.readFile)(gitignorePath, "utf-8");
|
|
2978
3142
|
const gitignoreDir = (0, import_path.dirname)(gitignorePath);
|
|
2979
|
-
const relativePrefix = (0, import_path.relative)(rootDir
|
|
3143
|
+
const relativePrefix = (0, import_path.relative)(rootDir, gitignoreDir).replace(
|
|
2980
3144
|
/\\/g,
|
|
2981
3145
|
"/"
|
|
2982
3146
|
);
|
|
@@ -2992,7 +3156,7 @@ async function scanEntries(options) {
|
|
|
2992
3156
|
}
|
|
2993
3157
|
}
|
|
2994
3158
|
const filteredDirs = dirs.filter((d) => {
|
|
2995
|
-
let rel = (0, import_path.relative)(rootDir
|
|
3159
|
+
let rel = (0, import_path.relative)(rootDir, d).replace(/\\/g, "/");
|
|
2996
3160
|
if (rel === "") return true;
|
|
2997
3161
|
if (!rel.endsWith("/")) rel += "/";
|
|
2998
3162
|
return !ig.ignores(rel);
|
|
@@ -3048,13 +3212,20 @@ function resolveOutputPath(userPath, defaultFilename, workingDir = process.cwd()
|
|
|
3048
3212
|
ensureDir(outputPath);
|
|
3049
3213
|
return outputPath;
|
|
3050
3214
|
}
|
|
3215
|
+
function safeJsonStringify(obj, indent = 2) {
|
|
3216
|
+
return JSON.stringify(
|
|
3217
|
+
obj,
|
|
3218
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v,
|
|
3219
|
+
indent
|
|
3220
|
+
);
|
|
3221
|
+
}
|
|
3051
3222
|
function handleJSONOutput(data, outputFile, successMessage) {
|
|
3052
3223
|
if (outputFile) {
|
|
3053
3224
|
ensureDir(outputFile);
|
|
3054
|
-
(0, import_fs2.writeFileSync)(outputFile,
|
|
3225
|
+
(0, import_fs2.writeFileSync)(outputFile, safeJsonStringify(data, 2));
|
|
3055
3226
|
console.log(successMessage || `\u2705 Results saved to ${outputFile}`);
|
|
3056
3227
|
} else {
|
|
3057
|
-
console.log(
|
|
3228
|
+
console.log(safeJsonStringify(data, 2));
|
|
3058
3229
|
}
|
|
3059
3230
|
}
|
|
3060
3231
|
function findLatestReport(dirPath) {
|
|
@@ -3245,7 +3416,7 @@ function handleCLIError(error, commandName) {
|
|
|
3245
3416
|
|
|
3246
3417
|
// src/utils/cli-helpers.ts
|
|
3247
3418
|
async function loadMergedConfig(directory, defaults, cliOptions) {
|
|
3248
|
-
const config = await loadConfig(directory);
|
|
3419
|
+
const { config } = await loadConfig(directory);
|
|
3249
3420
|
const mergedConfig = mergeConfigWithDefaults(config, defaults);
|
|
3250
3421
|
const result = {
|
|
3251
3422
|
...mergedConfig,
|
|
@@ -3780,8 +3951,7 @@ function estimateTokens(text) {
|
|
|
3780
3951
|
|
|
3781
3952
|
// src/utils/config.ts
|
|
3782
3953
|
var import_fs3 = require("fs");
|
|
3783
|
-
var
|
|
3784
|
-
var import_url2 = require("url");
|
|
3954
|
+
var import_path5 = require("path");
|
|
3785
3955
|
var CONFIG_FILES = [
|
|
3786
3956
|
"aiready.json",
|
|
3787
3957
|
"aiready.config.json",
|
|
@@ -3790,12 +3960,164 @@ var CONFIG_FILES = [
|
|
|
3790
3960
|
"aiready.config.js",
|
|
3791
3961
|
".aireadyrc.js"
|
|
3792
3962
|
];
|
|
3793
|
-
|
|
3794
|
-
|
|
3963
|
+
var DEFAULT_AUTO_EXCLUDE_PATTERNS = {
|
|
3964
|
+
tests: [
|
|
3965
|
+
"**/*.test.ts",
|
|
3966
|
+
"**/*.test.tsx",
|
|
3967
|
+
"**/*.test.js",
|
|
3968
|
+
"**/*.test.jsx",
|
|
3969
|
+
"**/*.spec.ts",
|
|
3970
|
+
"**/*.spec.tsx",
|
|
3971
|
+
"**/*.spec.js",
|
|
3972
|
+
"**/*.spec.jsx",
|
|
3973
|
+
"**/__tests__/**",
|
|
3974
|
+
"**/tests/**"
|
|
3975
|
+
],
|
|
3976
|
+
mocks: [
|
|
3977
|
+
"**/__mocks__/**",
|
|
3978
|
+
"**/*.mock.ts",
|
|
3979
|
+
"**/*.mock.tsx",
|
|
3980
|
+
"**/*.mock.js",
|
|
3981
|
+
"**/*.mock.jsx"
|
|
3982
|
+
],
|
|
3983
|
+
barrels: ["**/index.ts", "**/index.js"],
|
|
3984
|
+
generated: [
|
|
3985
|
+
"**/.next/**",
|
|
3986
|
+
"**/.sst/**",
|
|
3987
|
+
"**/.cache/**",
|
|
3988
|
+
"**/dist/**",
|
|
3989
|
+
"**/build/**"
|
|
3990
|
+
]
|
|
3991
|
+
};
|
|
3992
|
+
function deepMerge(base, override) {
|
|
3993
|
+
const result = { ...base };
|
|
3994
|
+
for (const key of Object.keys(override)) {
|
|
3995
|
+
const baseVal = base[key];
|
|
3996
|
+
const overrideVal = override[key];
|
|
3997
|
+
if (baseVal && overrideVal && typeof baseVal === "object" && typeof overrideVal === "object" && !Array.isArray(baseVal) && !Array.isArray(overrideVal)) {
|
|
3998
|
+
result[key] = deepMerge(baseVal, overrideVal);
|
|
3999
|
+
} else if (overrideVal !== void 0) {
|
|
4000
|
+
result[key] = overrideVal;
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
return result;
|
|
4004
|
+
}
|
|
4005
|
+
function checkPatternWarnings(config, configPath) {
|
|
4006
|
+
const warnings = [];
|
|
4007
|
+
const excludeArray = Array.isArray(config.exclude) ? config.exclude : config.exclude ? Object.values(config.exclude).flat() : [];
|
|
4008
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4009
|
+
for (const pattern of excludeArray) {
|
|
4010
|
+
if (seen.has(pattern)) {
|
|
4011
|
+
warnings.push({
|
|
4012
|
+
rule: "duplicate-exclude",
|
|
4013
|
+
message: `Duplicate pattern '${pattern}' in exclude array`
|
|
4014
|
+
});
|
|
4015
|
+
}
|
|
4016
|
+
seen.add(pattern);
|
|
4017
|
+
if (pattern.match(/^\*\*\/[^/]+\.[^/]+$/)) {
|
|
4018
|
+
warnings.push({
|
|
4019
|
+
rule: "single-file-glob",
|
|
4020
|
+
message: `Single-file glob '${pattern}' - use without ** prefix`,
|
|
4021
|
+
suggestion: pattern.replace(/^\*\*\//, "")
|
|
4022
|
+
});
|
|
4023
|
+
}
|
|
4024
|
+
const normalized = pattern.replace(/^\*\*\//, "").replace(/^\*\//, "");
|
|
4025
|
+
for (const other of seen) {
|
|
4026
|
+
if (other === pattern) continue;
|
|
4027
|
+
const otherNormalized = other.replace(/^\*\*\//, "").replace(/^\*\//, "");
|
|
4028
|
+
if (normalized === otherNormalized) {
|
|
4029
|
+
warnings.push({
|
|
4030
|
+
rule: "overlapping-pattern",
|
|
4031
|
+
message: `Patterns '${pattern}' and '${other}' likely match the same files`
|
|
4032
|
+
});
|
|
4033
|
+
}
|
|
4034
|
+
}
|
|
4035
|
+
}
|
|
4036
|
+
if (config.extends) {
|
|
4037
|
+
warnings.push({
|
|
4038
|
+
rule: "config-inheritance",
|
|
4039
|
+
message: `Config extends '${config.extends}' - ensure base config exists`
|
|
4040
|
+
});
|
|
4041
|
+
}
|
|
4042
|
+
return warnings;
|
|
4043
|
+
}
|
|
4044
|
+
function resolveConfigPath(extendsPath, baseConfigPath) {
|
|
4045
|
+
const baseDir = (0, import_path5.dirname)(baseConfigPath);
|
|
4046
|
+
return (0, import_path5.resolve)(baseDir, extendsPath);
|
|
4047
|
+
}
|
|
4048
|
+
async function loadConfigWithInheritance(configPath, alreadyLoaded = /* @__PURE__ */ new Set()) {
|
|
4049
|
+
const resolvedPath = (0, import_path5.resolve)(configPath);
|
|
4050
|
+
if (alreadyLoaded.has(resolvedPath)) {
|
|
4051
|
+
throw new Error(
|
|
4052
|
+
`Circular config inheritance detected: ${Array.from(alreadyLoaded).join(" -> ")} -> ${resolvedPath}`
|
|
4053
|
+
);
|
|
4054
|
+
}
|
|
4055
|
+
alreadyLoaded.add(resolvedPath);
|
|
4056
|
+
const content = (0, import_fs3.readFileSync)(resolvedPath, "utf-8");
|
|
4057
|
+
let rawConfig = JSON.parse(content);
|
|
4058
|
+
const warnings = [];
|
|
4059
|
+
const legacyKeys = ["toolConfigs", "scanConfig", "aiReady"];
|
|
4060
|
+
const foundLegacy = legacyKeys.filter((key) => key in rawConfig);
|
|
4061
|
+
if (foundLegacy.length > 0) {
|
|
4062
|
+
console.warn(
|
|
4063
|
+
`\u26A0\uFE0F Legacy configuration keys found: ${foundLegacy.join(", ")}. Please migrate to the new schema.`
|
|
4064
|
+
);
|
|
4065
|
+
}
|
|
4066
|
+
if (rawConfig.extends) {
|
|
4067
|
+
const baseConfigPath = resolveConfigPath(rawConfig.extends, resolvedPath);
|
|
4068
|
+
if (!(0, import_fs3.existsSync)(baseConfigPath)) {
|
|
4069
|
+
throw new Error(
|
|
4070
|
+
`Base config not found: ${rawConfig.extends} (resolved to ${baseConfigPath})`
|
|
4071
|
+
);
|
|
4072
|
+
}
|
|
4073
|
+
const baseResult = await loadConfigWithInheritance(
|
|
4074
|
+
baseConfigPath,
|
|
4075
|
+
alreadyLoaded
|
|
4076
|
+
);
|
|
4077
|
+
rawConfig = deepMerge(baseResult.config, rawConfig);
|
|
4078
|
+
warnings.push(...baseResult.warnings);
|
|
4079
|
+
}
|
|
4080
|
+
warnings.push(...checkPatternWarnings(rawConfig, resolvedPath));
|
|
4081
|
+
const config = AIReadyConfigSchema.parse(rawConfig);
|
|
4082
|
+
return { config, warnings };
|
|
4083
|
+
}
|
|
4084
|
+
function applyAutoExclusions(config, projectRoot) {
|
|
4085
|
+
const autoExclude = config.autoExclude ?? {
|
|
4086
|
+
tests: true,
|
|
4087
|
+
mocks: true,
|
|
4088
|
+
barrels: false,
|
|
4089
|
+
generated: true
|
|
4090
|
+
};
|
|
4091
|
+
if (!autoExclude.tests && !autoExclude.mocks && !autoExclude.barrels && !autoExclude.generated) {
|
|
4092
|
+
return config;
|
|
4093
|
+
}
|
|
4094
|
+
const patterns = [];
|
|
4095
|
+
if (autoExclude.tests) {
|
|
4096
|
+
patterns.push(...DEFAULT_AUTO_EXCLUDE_PATTERNS.tests);
|
|
4097
|
+
}
|
|
4098
|
+
if (autoExclude.mocks) {
|
|
4099
|
+
patterns.push(...DEFAULT_AUTO_EXCLUDE_PATTERNS.mocks);
|
|
4100
|
+
}
|
|
4101
|
+
if (autoExclude.barrels) {
|
|
4102
|
+
patterns.push(...DEFAULT_AUTO_EXCLUDE_PATTERNS.barrels);
|
|
4103
|
+
}
|
|
4104
|
+
if (autoExclude.generated) {
|
|
4105
|
+
patterns.push(...DEFAULT_AUTO_EXCLUDE_PATTERNS.generated);
|
|
4106
|
+
}
|
|
4107
|
+
const existingExclude = config.exclude ?? [];
|
|
4108
|
+
const existingArray = Array.isArray(existingExclude) ? existingExclude : existingExclude?.global ?? [];
|
|
4109
|
+
return {
|
|
4110
|
+
...config,
|
|
4111
|
+
exclude: [...existingArray, ...patterns]
|
|
4112
|
+
};
|
|
4113
|
+
}
|
|
4114
|
+
async function loadConfig(rootDir, options) {
|
|
4115
|
+
const warnings = [];
|
|
4116
|
+
let currentDir = (0, import_path5.resolve)(rootDir);
|
|
3795
4117
|
while (true) {
|
|
3796
4118
|
const foundConfigs = [];
|
|
3797
4119
|
for (const configFile of CONFIG_FILES) {
|
|
3798
|
-
if ((0, import_fs3.existsSync)((0,
|
|
4120
|
+
if ((0, import_fs3.existsSync)((0, import_path5.join)(currentDir, configFile))) {
|
|
3799
4121
|
foundConfigs.push(configFile);
|
|
3800
4122
|
}
|
|
3801
4123
|
}
|
|
@@ -3806,39 +4128,17 @@ async function loadConfig(rootDir) {
|
|
|
3806
4128
|
", "
|
|
3807
4129
|
)}. Using ${foundConfigs[0]}.`
|
|
3808
4130
|
);
|
|
3809
|
-
} else {
|
|
3810
4131
|
}
|
|
3811
4132
|
const configFile = foundConfigs[0];
|
|
3812
|
-
const configPath = (0,
|
|
4133
|
+
const configPath = (0, import_path5.join)(currentDir, configFile);
|
|
3813
4134
|
try {
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
config =
|
|
3819
|
-
} else {
|
|
3820
|
-
const content = (0, import_fs3.readFileSync)(configPath, "utf-8");
|
|
3821
|
-
config = JSON.parse(content);
|
|
4135
|
+
const result = await loadConfigWithInheritance(configPath);
|
|
4136
|
+
warnings.push(...result.warnings);
|
|
4137
|
+
let config = result.config;
|
|
4138
|
+
if (options?.applyAutoExclude !== false) {
|
|
4139
|
+
config = applyAutoExclusions(config, currentDir);
|
|
3822
4140
|
}
|
|
3823
|
-
|
|
3824
|
-
const rootLevelTools = [
|
|
3825
|
-
"pattern-detect",
|
|
3826
|
-
"context-analyzer",
|
|
3827
|
-
"naming-consistency",
|
|
3828
|
-
"ai-signal-clarity"
|
|
3829
|
-
];
|
|
3830
|
-
const allKeys = Object.keys(config);
|
|
3831
|
-
const foundLegacy = allKeys.filter(
|
|
3832
|
-
(k) => legacyKeys.includes(k) || rootLevelTools.includes(k)
|
|
3833
|
-
);
|
|
3834
|
-
if (foundLegacy.length > 0) {
|
|
3835
|
-
console.warn(
|
|
3836
|
-
`\u26A0\uFE0F Legacy configuration keys found: ${foundLegacy.join(
|
|
3837
|
-
", "
|
|
3838
|
-
)}. These are deprecated and should be moved under the "tools" key.`
|
|
3839
|
-
);
|
|
3840
|
-
}
|
|
3841
|
-
return AIReadyConfigSchema.parse(config);
|
|
4141
|
+
return { config, warnings };
|
|
3842
4142
|
} catch (error) {
|
|
3843
4143
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3844
4144
|
const configError = new Error(
|
|
@@ -3851,13 +4151,27 @@ async function loadConfig(rootDir) {
|
|
|
3851
4151
|
throw configError;
|
|
3852
4152
|
}
|
|
3853
4153
|
}
|
|
3854
|
-
const parent = (0,
|
|
4154
|
+
const parent = (0, import_path5.dirname)(currentDir);
|
|
3855
4155
|
if (parent === currentDir) {
|
|
3856
4156
|
break;
|
|
3857
4157
|
}
|
|
3858
4158
|
currentDir = parent;
|
|
3859
4159
|
}
|
|
3860
|
-
return null;
|
|
4160
|
+
return { config: null, warnings };
|
|
4161
|
+
}
|
|
4162
|
+
function validateConfig(configPath) {
|
|
4163
|
+
try {
|
|
4164
|
+
const content = (0, import_fs3.readFileSync)(configPath, "utf-8");
|
|
4165
|
+
const config = JSON.parse(content);
|
|
4166
|
+
return checkPatternWarnings(config, configPath);
|
|
4167
|
+
} catch (error) {
|
|
4168
|
+
return [
|
|
4169
|
+
{
|
|
4170
|
+
rule: "parse-error",
|
|
4171
|
+
message: `Failed to parse config: ${error instanceof Error ? error.message : String(error)}`
|
|
4172
|
+
}
|
|
4173
|
+
];
|
|
4174
|
+
}
|
|
3861
4175
|
}
|
|
3862
4176
|
function mergeConfigWithDefaults(userConfig, defaults) {
|
|
3863
4177
|
if (!userConfig) return defaults;
|
|
@@ -5003,6 +5317,9 @@ function extractBlocksPython(file, content) {
|
|
|
5003
5317
|
return blocks;
|
|
5004
5318
|
}
|
|
5005
5319
|
|
|
5320
|
+
// src/index.ts
|
|
5321
|
+
init_path_utils();
|
|
5322
|
+
|
|
5006
5323
|
// src/business/pricing-models.ts
|
|
5007
5324
|
var MODEL_PRICING_PRESETS = {
|
|
5008
5325
|
"gpt-5.4-mini": {
|
|
@@ -6565,9 +6882,9 @@ function calculateChangeAmplification(params) {
|
|
|
6565
6882
|
|
|
6566
6883
|
// src/utils/history.ts
|
|
6567
6884
|
var import_fs4 = require("fs");
|
|
6568
|
-
var
|
|
6885
|
+
var import_path6 = require("path");
|
|
6569
6886
|
function getHistoryPath(rootDir) {
|
|
6570
|
-
return (0,
|
|
6887
|
+
return (0, import_path6.join)(rootDir, ".aiready", "history.json");
|
|
6571
6888
|
}
|
|
6572
6889
|
function loadScoreHistory(rootDir) {
|
|
6573
6890
|
const historyPath = getHistoryPath(rootDir);
|
|
@@ -6584,7 +6901,7 @@ function loadScoreHistory(rootDir) {
|
|
|
6584
6901
|
}
|
|
6585
6902
|
function saveScoreEntry(rootDir, entry) {
|
|
6586
6903
|
const historyPath = getHistoryPath(rootDir);
|
|
6587
|
-
const historyDir = (0,
|
|
6904
|
+
const historyDir = (0, import_path6.dirname)(historyPath);
|
|
6588
6905
|
if (!(0, import_fs4.existsSync)(historyDir)) {
|
|
6589
6906
|
(0, import_fs4.mkdirSync)(historyDir, { recursive: true });
|
|
6590
6907
|
}
|
|
@@ -6637,78 +6954,6 @@ function clearHistory(rootDir) {
|
|
|
6637
6954
|
}
|
|
6638
6955
|
}
|
|
6639
6956
|
|
|
6640
|
-
// src/utils/history-git.ts
|
|
6641
|
-
var import_child_process = require("child_process");
|
|
6642
|
-
function getFileCommitTimestamps(file) {
|
|
6643
|
-
const lineStamps = {};
|
|
6644
|
-
try {
|
|
6645
|
-
const output = (0, import_child_process.execSync)(`git blame -t "${file}"`, {
|
|
6646
|
-
encoding: "utf-8",
|
|
6647
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
6648
|
-
});
|
|
6649
|
-
const lines = output.split("\n");
|
|
6650
|
-
for (const line of lines) {
|
|
6651
|
-
if (!line) continue;
|
|
6652
|
-
const match = line.match(/^\S+\s+\(.*?(\d{10,})\s+[-+]\d+\s+(\d+)\)/);
|
|
6653
|
-
if (match) {
|
|
6654
|
-
const ts = parseInt(match[1], 10);
|
|
6655
|
-
const ln = parseInt(match[2], 10);
|
|
6656
|
-
lineStamps[ln] = ts;
|
|
6657
|
-
}
|
|
6658
|
-
}
|
|
6659
|
-
} catch {
|
|
6660
|
-
}
|
|
6661
|
-
return lineStamps;
|
|
6662
|
-
}
|
|
6663
|
-
function getLineRangeLastModifiedCached(lineStamps, startLine, endLine) {
|
|
6664
|
-
let latest = 0;
|
|
6665
|
-
for (let i = startLine; i <= endLine; i++) {
|
|
6666
|
-
if (lineStamps[i] && lineStamps[i] > latest) {
|
|
6667
|
-
latest = lineStamps[i];
|
|
6668
|
-
}
|
|
6669
|
-
}
|
|
6670
|
-
return latest;
|
|
6671
|
-
}
|
|
6672
|
-
function getRepoMetadata(directory) {
|
|
6673
|
-
const metadata = {};
|
|
6674
|
-
try {
|
|
6675
|
-
try {
|
|
6676
|
-
metadata.url = (0, import_child_process.execSync)("git config --get remote.origin.url", {
|
|
6677
|
-
cwd: directory,
|
|
6678
|
-
encoding: "utf-8",
|
|
6679
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
6680
|
-
}).trim();
|
|
6681
|
-
} catch {
|
|
6682
|
-
}
|
|
6683
|
-
try {
|
|
6684
|
-
metadata.branch = (0, import_child_process.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
6685
|
-
cwd: directory,
|
|
6686
|
-
encoding: "utf-8",
|
|
6687
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
6688
|
-
}).trim();
|
|
6689
|
-
} catch {
|
|
6690
|
-
}
|
|
6691
|
-
try {
|
|
6692
|
-
metadata.commit = (0, import_child_process.execSync)("git rev-parse HEAD", {
|
|
6693
|
-
cwd: directory,
|
|
6694
|
-
encoding: "utf-8",
|
|
6695
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
6696
|
-
}).trim();
|
|
6697
|
-
} catch {
|
|
6698
|
-
}
|
|
6699
|
-
try {
|
|
6700
|
-
metadata.author = (0, import_child_process.execSync)("git log -1 --format=%ae", {
|
|
6701
|
-
cwd: directory,
|
|
6702
|
-
encoding: "utf-8",
|
|
6703
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
6704
|
-
}).trim();
|
|
6705
|
-
} catch {
|
|
6706
|
-
}
|
|
6707
|
-
} catch {
|
|
6708
|
-
}
|
|
6709
|
-
return metadata;
|
|
6710
|
-
}
|
|
6711
|
-
|
|
6712
6957
|
// src/utils/github-utils.ts
|
|
6713
6958
|
function emitAnnotation(params) {
|
|
6714
6959
|
const { level, file, line, col, title, message } = params;
|
|
@@ -6797,7 +7042,7 @@ Found ${issues.length} issues.`));
|
|
|
6797
7042
|
|
|
6798
7043
|
// src/utils/test-utils.ts
|
|
6799
7044
|
var import_fs5 = require("fs");
|
|
6800
|
-
var
|
|
7045
|
+
var import_path7 = require("path");
|
|
6801
7046
|
var TEST_PATTERNS = [
|
|
6802
7047
|
// TypeScript/JavaScript test files
|
|
6803
7048
|
/\.(test|spec)\.(ts|tsx|js|jsx)$/,
|
|
@@ -6862,7 +7107,7 @@ function detectTestFramework(rootDir) {
|
|
|
6862
7107
|
// go testing is built-in
|
|
6863
7108
|
];
|
|
6864
7109
|
for (const m of manifests) {
|
|
6865
|
-
const p = (0,
|
|
7110
|
+
const p = (0, import_path7.join)(rootDir, m.file);
|
|
6866
7111
|
if ((0, import_fs5.existsSync)(p)) {
|
|
6867
7112
|
if (m.file === "go.mod") return true;
|
|
6868
7113
|
try {
|
|
@@ -6920,6 +7165,188 @@ async function withErrorHandling(operation, context) {
|
|
|
6920
7165
|
return { success: false, error: `${contextPrefix}${message}` };
|
|
6921
7166
|
}
|
|
6922
7167
|
}
|
|
7168
|
+
|
|
7169
|
+
// src/growth/agents.ts
|
|
7170
|
+
var import_child_process2 = require("child_process");
|
|
7171
|
+
var GitHubIssueResolverAgent = class {
|
|
7172
|
+
constructor(options) {
|
|
7173
|
+
this.generate = options.generate;
|
|
7174
|
+
if (!options.trustedAuthors || options.trustedAuthors.length === 0) {
|
|
7175
|
+
throw new Error(
|
|
7176
|
+
"[GitHubIssueResolverAgent] Security Error: trustedAuthors must be explicitly configured."
|
|
7177
|
+
);
|
|
7178
|
+
}
|
|
7179
|
+
this.trustedAuthors = options.trustedAuthors;
|
|
7180
|
+
}
|
|
7181
|
+
async resolve(issue, workingDir) {
|
|
7182
|
+
console.log(
|
|
7183
|
+
`[GitHubIssueResolverAgent] Resolving issue #${issue.number}: ${issue.title}`
|
|
7184
|
+
);
|
|
7185
|
+
const strategy = await this.identifyStrategy(issue);
|
|
7186
|
+
console.log(`[GitHubIssueResolverAgent] Selected Strategy: ${strategy}`);
|
|
7187
|
+
try {
|
|
7188
|
+
switch (strategy) {
|
|
7189
|
+
case "CORE_EVOLUTION_SYNC":
|
|
7190
|
+
if (issue.author && !this.trustedAuthors.includes(issue.author)) {
|
|
7191
|
+
console.warn(
|
|
7192
|
+
`[GitHubIssueResolverAgent] Unauthorized evolution attempt by ${issue.author}. Blocking.`
|
|
7193
|
+
);
|
|
7194
|
+
return {
|
|
7195
|
+
success: false,
|
|
7196
|
+
message: `Unauthorized actor: ${issue.author} is not in trustedAuthors list.`
|
|
7197
|
+
};
|
|
7198
|
+
}
|
|
7199
|
+
return await this.executeSubtreeSync(issue, workingDir);
|
|
7200
|
+
case "EVOLUTION_CONTRIBUTION":
|
|
7201
|
+
return await this.applyContributionPattern(issue, workingDir);
|
|
7202
|
+
case "BUG_FIX":
|
|
7203
|
+
return await this.applyAgenticPatch(issue, workingDir);
|
|
7204
|
+
default:
|
|
7205
|
+
return { success: false, message: `Unknown strategy: ${strategy}` };
|
|
7206
|
+
}
|
|
7207
|
+
} catch (error) {
|
|
7208
|
+
console.error(
|
|
7209
|
+
`[GitHubIssueResolverAgent] Resolution failed for issue #${issue.number}:`,
|
|
7210
|
+
error.message
|
|
7211
|
+
);
|
|
7212
|
+
return {
|
|
7213
|
+
success: false,
|
|
7214
|
+
message: `Resolution failed: ${error.message}`
|
|
7215
|
+
};
|
|
7216
|
+
}
|
|
7217
|
+
}
|
|
7218
|
+
async identifyStrategy(issue) {
|
|
7219
|
+
if (issue.labels.includes("evolution-sync")) return "CORE_EVOLUTION_SYNC";
|
|
7220
|
+
if (issue.labels.includes("evolution-contribution"))
|
|
7221
|
+
return "EVOLUTION_CONTRIBUTION";
|
|
7222
|
+
if (issue.labels.includes("bug")) return "BUG_FIX";
|
|
7223
|
+
const prompt = `
|
|
7224
|
+
Analyze the GitHub Issue:
|
|
7225
|
+
Title: ${issue.title}
|
|
7226
|
+
Labels: ${issue.labels.join(", ")}
|
|
7227
|
+
|
|
7228
|
+
Categorize into: CORE_EVOLUTION_SYNC, EVOLUTION_CONTRIBUTION, BUG_FIX, or UNKNOWN.
|
|
7229
|
+
Only return the category name.
|
|
7230
|
+
`;
|
|
7231
|
+
return (await this.generate(prompt)).trim();
|
|
7232
|
+
}
|
|
7233
|
+
async executeSubtreeSync(issue, workingDir) {
|
|
7234
|
+
const hubVersion = this.extractVersion(issue.body);
|
|
7235
|
+
const prefix = "core/";
|
|
7236
|
+
const hubUrl = "https://github.com/serverlessclaw/serverlessclaw.git";
|
|
7237
|
+
console.log(
|
|
7238
|
+
`[GitHubIssueResolverAgent] Performing Subtree Pull (Hub v${hubVersion}) into ${workingDir}...`
|
|
7239
|
+
);
|
|
7240
|
+
try {
|
|
7241
|
+
try {
|
|
7242
|
+
(0, import_child_process2.execSync)(`git remote add hub ${hubUrl}`, {
|
|
7243
|
+
cwd: workingDir,
|
|
7244
|
+
stdio: "ignore"
|
|
7245
|
+
});
|
|
7246
|
+
} catch (e) {
|
|
7247
|
+
if (!e.message.includes("already exists")) {
|
|
7248
|
+
console.warn(
|
|
7249
|
+
`[GitHubIssueResolverAgent] Remote add warning: ${e.message}`
|
|
7250
|
+
);
|
|
7251
|
+
}
|
|
7252
|
+
}
|
|
7253
|
+
(0, import_child_process2.execSync)(`git fetch hub`, { cwd: workingDir, stdio: "pipe" });
|
|
7254
|
+
console.log(
|
|
7255
|
+
`[GitHubIssueResolverAgent] Executing subtree pull for v${hubVersion}...`
|
|
7256
|
+
);
|
|
7257
|
+
(0, import_child_process2.execSync)(
|
|
7258
|
+
`git subtree pull --prefix=${prefix} hub ${hubVersion} --squash -m "chore(sync): evolution upgrade to ${hubVersion}"`,
|
|
7259
|
+
{
|
|
7260
|
+
cwd: workingDir,
|
|
7261
|
+
env: { ...process.env, GIT_MERGE_AUTOEDIT: "no" }
|
|
7262
|
+
}
|
|
7263
|
+
);
|
|
7264
|
+
return {
|
|
7265
|
+
success: true,
|
|
7266
|
+
message: `Successfully sync'd Hub ${hubVersion} via subtree merge`
|
|
7267
|
+
};
|
|
7268
|
+
} catch (error) {
|
|
7269
|
+
console.error(
|
|
7270
|
+
`[GitHubIssueResolverAgent] Subtree sync failed: ${error.message}`
|
|
7271
|
+
);
|
|
7272
|
+
throw new Error(`Subtree sync failed: ${error.message}`, {
|
|
7273
|
+
cause: error
|
|
7274
|
+
});
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
async applyContributionPattern(issue, workingDir) {
|
|
7278
|
+
console.log(
|
|
7279
|
+
`[GitHubIssueResolverAgent] Pattern absorption requested: ${issue.title}`
|
|
7280
|
+
);
|
|
7281
|
+
return {
|
|
7282
|
+
success: true,
|
|
7283
|
+
message: `Contribution strategy identified. Pattern "${issue.title}" is ready for human screening and promotion.`
|
|
7284
|
+
};
|
|
7285
|
+
}
|
|
7286
|
+
async applyAgenticPatch(issue, workingDir) {
|
|
7287
|
+
console.log(`[GitHubIssueResolverAgent] Bug fix requested: ${issue.title}`);
|
|
7288
|
+
return {
|
|
7289
|
+
success: true,
|
|
7290
|
+
message: `Patch strategy identified. Agentic fix for "${issue.title}" is being drafted.`
|
|
7291
|
+
};
|
|
7292
|
+
}
|
|
7293
|
+
extractVersion(body) {
|
|
7294
|
+
const match = body.match(/v\d+\.\d+\.\d+/);
|
|
7295
|
+
if (match) return match[0];
|
|
7296
|
+
const branchMatch = body.match(/branch:?\s*([a-zA-Z0-9.\-_/]+)/i);
|
|
7297
|
+
if (branchMatch) return branchMatch[1];
|
|
7298
|
+
return "main";
|
|
7299
|
+
}
|
|
7300
|
+
};
|
|
7301
|
+
|
|
7302
|
+
// src/services/github-service.ts
|
|
7303
|
+
var import_rest = require("@octokit/rest");
|
|
7304
|
+
var GitHubService = class {
|
|
7305
|
+
constructor(token) {
|
|
7306
|
+
this.octokit = new import_rest.Octokit({ auth: token });
|
|
7307
|
+
}
|
|
7308
|
+
/**
|
|
7309
|
+
* Creates an issue in a repository.
|
|
7310
|
+
*/
|
|
7311
|
+
async createHubIssue(owner, repo, issue) {
|
|
7312
|
+
const { data } = await this.octokit.issues.create({
|
|
7313
|
+
owner,
|
|
7314
|
+
repo,
|
|
7315
|
+
title: issue.title,
|
|
7316
|
+
body: issue.body,
|
|
7317
|
+
labels: issue.labels || ["innovation-harvest"]
|
|
7318
|
+
});
|
|
7319
|
+
return data.number;
|
|
7320
|
+
}
|
|
7321
|
+
/**
|
|
7322
|
+
* Creates a Pull Request in a repository.
|
|
7323
|
+
*/
|
|
7324
|
+
async createPullRequest(owner, repo, pr) {
|
|
7325
|
+
const { data } = await this.octokit.pulls.create({
|
|
7326
|
+
owner,
|
|
7327
|
+
repo,
|
|
7328
|
+
title: pr.title,
|
|
7329
|
+
body: pr.body,
|
|
7330
|
+
head: pr.head,
|
|
7331
|
+
base: pr.base
|
|
7332
|
+
});
|
|
7333
|
+
return data.number;
|
|
7334
|
+
}
|
|
7335
|
+
/**
|
|
7336
|
+
* Scans a repository content.
|
|
7337
|
+
*/
|
|
7338
|
+
async listRecentChangesInRepo(owner, repo, path2 = "") {
|
|
7339
|
+
const { data } = await this.octokit.repos.getContent({
|
|
7340
|
+
owner,
|
|
7341
|
+
repo,
|
|
7342
|
+
path: path2
|
|
7343
|
+
});
|
|
7344
|
+
if (Array.isArray(data)) {
|
|
7345
|
+
return data.map((file) => file.path);
|
|
7346
|
+
}
|
|
7347
|
+
return [];
|
|
7348
|
+
}
|
|
7349
|
+
};
|
|
6923
7350
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6924
7351
|
0 && (module.exports = {
|
|
6925
7352
|
AIReadyConfigSchema,
|
|
@@ -6930,6 +7357,7 @@ async function withErrorHandling(operation, context) {
|
|
|
6930
7357
|
COMMON_FINE_TUNING_OPTIONS,
|
|
6931
7358
|
CONTEXT_TIER_THRESHOLDS,
|
|
6932
7359
|
CSharpParser,
|
|
7360
|
+
DEFAULT_AUTO_EXCLUDE_PATTERNS,
|
|
6933
7361
|
DEFAULT_COST_CONFIG,
|
|
6934
7362
|
DEFAULT_EXCLUDE,
|
|
6935
7363
|
DEFAULT_TOOL_WEIGHTS,
|
|
@@ -6938,6 +7366,8 @@ async function withErrorHandling(operation, context) {
|
|
|
6938
7366
|
FRIENDLY_TOOL_NAMES,
|
|
6939
7367
|
GLOBAL_INFRA_OPTIONS,
|
|
6940
7368
|
GLOBAL_SCAN_OPTIONS,
|
|
7369
|
+
GitHubIssueResolverAgent,
|
|
7370
|
+
GitHubService,
|
|
6941
7371
|
GoParser,
|
|
6942
7372
|
IssueSchema,
|
|
6943
7373
|
IssueType,
|
|
@@ -7042,6 +7472,8 @@ async function withErrorHandling(operation, context) {
|
|
|
7042
7472
|
generateStatCards,
|
|
7043
7473
|
generateTable,
|
|
7044
7474
|
generateValueChain,
|
|
7475
|
+
getChangedFiles,
|
|
7476
|
+
getDirname,
|
|
7045
7477
|
getElapsedTime,
|
|
7046
7478
|
getErrorMessage,
|
|
7047
7479
|
getFileCommitTimestamps,
|
|
@@ -7110,12 +7542,14 @@ async function withErrorHandling(operation, context) {
|
|
|
7110
7542
|
resolveOutputPath,
|
|
7111
7543
|
runBatchAnalysis,
|
|
7112
7544
|
runStandardCliAction,
|
|
7545
|
+
safeJsonStringify,
|
|
7113
7546
|
saveScoreEntry,
|
|
7114
7547
|
scanEntries,
|
|
7115
7548
|
scanFiles,
|
|
7116
7549
|
setupParser,
|
|
7117
7550
|
severityToAnnotationLevel,
|
|
7118
7551
|
toErrorMessage,
|
|
7552
|
+
validateConfig,
|
|
7119
7553
|
validateSpokeOutput,
|
|
7120
7554
|
validateWithSchema,
|
|
7121
7555
|
withErrorHandling,
|