bugzero 0.0.36 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.js +119 -55
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ bugzero rescue
|
|
|
92
92
|
|
|
93
93
|
### Repair engine
|
|
94
94
|
|
|
95
|
-
- **Autonomous repair loop.** `bugzero rescue` runs your build, lint, and tests. When something fails, it sends the error output — along with the relevant source files and directory listings as context — to an LLM, applies the fix the model proposes, and re-runs validation. It repeats, feeding any patch failures back to the model, until everything passes or the attempt limit is reached (3 by default; change it with `--max-attempts
|
|
95
|
+
- **Autonomous repair loop.** `bugzero rescue` runs your build, lint, and tests. When something fails, it sends the error output — along with the relevant source files and directory listings as context — to an LLM, applies the fix the model proposes, and re-runs validation. It repeats, feeding any patch failures back to the model, until everything passes or the attempt limit is reached (3 by default; change it with `--max-attempts`, which accepts any whole number of 1 or more). The loop is a stateful LangGraph graph: analyze, patch, verify.
|
|
96
96
|
- **Multi-file patches.** One fix can edit several files at once — for example, a renamed export plus every file that imports it. All patches in an attempt are applied as a single atomic unit: if any one of them fails to apply, every file touched in that attempt is restored to its original content, so you never end up with a half-applied fix.
|
|
97
97
|
- **Fuzzy patch matching.** LLMs rarely reproduce code byte-for-byte, so BugZero locates each patch in three tiers: an exact match first, then a whitespace-normalized line match (tolerates indentation and spacing drift), then a similarity-scored match (average per-line similarity of at least 85%). If two locations look equally plausible, it refuses to guess and reports a failed patch instead of risking an edit in the wrong place.
|
|
98
98
|
- **Multi-model support.** Works with any model available on OpenRouter — DeepSeek, Claude, Gemini, GPT-4o, Llama, and more. Choose one interactively with `bugzero vibe`; the choice is saved per project in `.bugzerorc`.
|
|
@@ -101,11 +101,13 @@ bugzero rescue
|
|
|
101
101
|
|
|
102
102
|
- **Backups on every patch.** Each file BugZero modifies gets a `.opspilot.bak` copy of its original content first.
|
|
103
103
|
- **Dry-run mode.** `bugzero rescue --dry-run` runs validation and error analysis, but makes no fix attempts and never modifies your source files (a report is still written).
|
|
104
|
+
- **Prompt size limits.** Very long error output and very large source files are shortened before being sent to the model (for logs, the start and end are kept), so a big failure can't exceed the model's context window or waste tokens.
|
|
104
105
|
|
|
105
106
|
### Project awareness
|
|
106
107
|
|
|
107
108
|
- **Framework detection.** Identifies Next.js, NestJS, Vite, Remix, Astro, SvelteKit, Nuxt, Angular, Create React App, or a plain TypeScript project from its config files and dependencies, and shows the result in the run banner.
|
|
108
109
|
- **Package manager detection.** Runs build, lint, and test with the tool your project actually uses — npm, pnpm, yarn, or bun. It checks the `packageManager` field in `package.json` first, then `pnpm-workspace.yaml` or a lockfile, and falls back to npm.
|
|
110
|
+
- **Script-aware validation.** Only runs the build, lint, and test scripts your `package.json` actually defines. A missing script is reported as skipped rather than failed, so a project without a `lint` script no longer shows a false lint failure. Pointing `--path` at a directory with no `package.json` stops immediately with a clear error.
|
|
109
111
|
- **Error parsing.** Recognizes TypeScript compiler errors (file, line, column, message), ESLint errors, and Jest failures to classify what broke and how many errors were found. Output in any other format is still passed to the model as raw logs.
|
|
110
112
|
|
|
111
113
|
### Integrations and output
|
package/dist/index.js
CHANGED
|
@@ -469,15 +469,19 @@ var require_dist2 = __commonJS({
|
|
|
469
469
|
detectPackageManager: () => detectPackageManager3,
|
|
470
470
|
getRunScriptCommand: () => getRunScriptCommand,
|
|
471
471
|
parseErrors: () => parseErrors,
|
|
472
|
+
readScripts: () => readScripts,
|
|
472
473
|
runBuild: () => runBuild,
|
|
473
474
|
runCommand: () => runCommand,
|
|
474
475
|
runLint: () => runLint,
|
|
476
|
+
runScript: () => runScript,
|
|
475
477
|
runTests: () => runTests,
|
|
476
478
|
runValidationPipeline: () => runValidationPipeline
|
|
477
479
|
});
|
|
478
480
|
module2.exports = __toCommonJS(index_exports);
|
|
479
481
|
var import_fs2 = __toESM2(require("fs"));
|
|
480
482
|
var import_path2 = __toESM2(require("path"));
|
|
483
|
+
var import_fs3 = __toESM2(require("fs"));
|
|
484
|
+
var import_path3 = __toESM2(require("path"));
|
|
481
485
|
var VALID_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
|
|
482
486
|
var LOCKFILE_MANAGERS = [
|
|
483
487
|
{ file: "pnpm-workspace.yaml", manager: "pnpm" },
|
|
@@ -489,9 +493,9 @@ var require_dist2 = __commonJS({
|
|
|
489
493
|
];
|
|
490
494
|
function detectPackageManager3(cwd = process.cwd()) {
|
|
491
495
|
try {
|
|
492
|
-
const pkgPath =
|
|
493
|
-
if (
|
|
494
|
-
const pkg = JSON.parse(
|
|
496
|
+
const pkgPath = import_path3.default.join(cwd, "package.json");
|
|
497
|
+
if (import_fs3.default.existsSync(pkgPath)) {
|
|
498
|
+
const pkg = JSON.parse(import_fs3.default.readFileSync(pkgPath, "utf-8"));
|
|
495
499
|
if (typeof pkg.packageManager === "string") {
|
|
496
500
|
const name = pkg.packageManager.split("@")[0].trim();
|
|
497
501
|
if (VALID_MANAGERS.includes(name)) {
|
|
@@ -502,7 +506,7 @@ var require_dist2 = __commonJS({
|
|
|
502
506
|
} catch {
|
|
503
507
|
}
|
|
504
508
|
for (const { file, manager } of LOCKFILE_MANAGERS) {
|
|
505
|
-
if (
|
|
509
|
+
if (import_fs3.default.existsSync(import_path3.default.join(cwd, file))) return manager;
|
|
506
510
|
}
|
|
507
511
|
return "npm";
|
|
508
512
|
}
|
|
@@ -532,9 +536,26 @@ var require_dist2 = __commonJS({
|
|
|
532
536
|
};
|
|
533
537
|
}
|
|
534
538
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
539
|
+
function readScripts(cwd = process.cwd()) {
|
|
540
|
+
try {
|
|
541
|
+
const pkgPath = import_path2.default.join(cwd, "package.json");
|
|
542
|
+
if (!import_fs2.default.existsSync(pkgPath)) return [];
|
|
543
|
+
const pkg = JSON.parse(import_fs2.default.readFileSync(pkgPath, "utf-8"));
|
|
544
|
+
if (typeof pkg.scripts !== "object" || pkg.scripts === null) return [];
|
|
545
|
+
return Object.keys(pkg.scripts);
|
|
546
|
+
} catch {
|
|
547
|
+
return [];
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
async function runScript(script, cwd) {
|
|
551
|
+
if (!readScripts(cwd).includes(script)) {
|
|
552
|
+
return { success: true, output: "", skipped: true };
|
|
553
|
+
}
|
|
554
|
+
return runCommand(getRunScriptCommand(detectPackageManager3(cwd), script), cwd);
|
|
555
|
+
}
|
|
556
|
+
var runBuild = (cwd) => runScript("build", cwd);
|
|
557
|
+
var runLint = (cwd) => runScript("lint", cwd);
|
|
558
|
+
var runTests = (cwd) => runScript("test", cwd);
|
|
538
559
|
var TS_ERROR_RE = /^(.+)\((\d+),(\d+)\):\s+error\s+TS\d+:\s+(.+)$/gm;
|
|
539
560
|
var ESLINT_ERROR_RE = /^\s+(\d+):(\d+)\s+error\s+(.+)$/gm;
|
|
540
561
|
var JEST_FAIL_RE = /● (.+)/g;
|
|
@@ -584,37 +605,29 @@ var require_dist2 = __commonJS({
|
|
|
584
605
|
}
|
|
585
606
|
return errors;
|
|
586
607
|
}
|
|
587
|
-
var
|
|
588
|
-
|
|
608
|
+
var STEPS = [
|
|
609
|
+
{ step: "build", label: "build", run: runBuild },
|
|
610
|
+
{ step: "lint", label: "lint", run: runLint },
|
|
611
|
+
{ step: "test", label: "tests", run: runTests }
|
|
612
|
+
];
|
|
589
613
|
async function runValidationPipeline(cwd) {
|
|
590
614
|
const targetCwd = cwd ?? process.cwd();
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
if (
|
|
595
|
-
|
|
596
|
-
|
|
615
|
+
const scripts = readScripts(targetCwd);
|
|
616
|
+
let ranAnyStep = false;
|
|
617
|
+
for (const { step, label, run } of STEPS) {
|
|
618
|
+
if (!scripts.includes(step)) {
|
|
619
|
+
console.log(`[BugZero] Skipping ${label}: no "${step}" script in package.json.`);
|
|
620
|
+
continue;
|
|
597
621
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
return { success: false, step: "build", output: buildRes.output };
|
|
604
|
-
}
|
|
605
|
-
if (scripts.includes("lint")) {
|
|
606
|
-
console.log(`[BugZero] Running lint...`);
|
|
607
|
-
const lintRes = await runLint(targetCwd);
|
|
608
|
-
if (!lintRes.success) {
|
|
609
|
-
return { success: false, step: "lint", output: lintRes.output };
|
|
622
|
+
ranAnyStep = true;
|
|
623
|
+
console.log(`[BugZero] Running ${label}...`);
|
|
624
|
+
const result = await run(targetCwd);
|
|
625
|
+
if (!result.success) {
|
|
626
|
+
return { success: false, step, output: result.output };
|
|
610
627
|
}
|
|
611
628
|
}
|
|
612
|
-
if (
|
|
613
|
-
console.
|
|
614
|
-
const testRes = await runTests(targetCwd);
|
|
615
|
-
if (!testRes.success) {
|
|
616
|
-
return { success: false, step: "test", output: testRes.output };
|
|
617
|
-
}
|
|
629
|
+
if (!ranAnyStep) {
|
|
630
|
+
console.warn(`[BugZero] No build, lint, or test scripts found in package.json \u2014 nothing to validate.`);
|
|
618
631
|
}
|
|
619
632
|
return { success: true, step: "none", output: "" };
|
|
620
633
|
}
|
|
@@ -777,11 +790,26 @@ var require_dist4 = __commonJS({
|
|
|
777
790
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
778
791
|
var index_exports = {};
|
|
779
792
|
__export(index_exports, {
|
|
780
|
-
buildAnalysisPrompt: () => buildAnalysisPrompt
|
|
793
|
+
buildAnalysisPrompt: () => buildAnalysisPrompt,
|
|
794
|
+
truncateLogs: () => truncateLogs
|
|
781
795
|
});
|
|
782
796
|
module2.exports = __toCommonJS(index_exports);
|
|
783
797
|
var import_fs2 = __toESM2(require("fs"));
|
|
784
798
|
var import_path2 = __toESM2(require("path"));
|
|
799
|
+
var MAX_LOG_CHARS = 2e4;
|
|
800
|
+
var MAX_FILE_CHARS = 2e4;
|
|
801
|
+
var MAX_CONTEXT_CHARS = 6e4;
|
|
802
|
+
function truncateLogs(logs, maxChars = MAX_LOG_CHARS) {
|
|
803
|
+
if (logs.length <= maxChars) return logs;
|
|
804
|
+
const head = logs.slice(0, Math.floor(maxChars * 0.6));
|
|
805
|
+
const tail = logs.slice(logs.length - Math.floor(maxChars * 0.4));
|
|
806
|
+
const omitted = logs.length - head.length - tail.length;
|
|
807
|
+
return `${head}
|
|
808
|
+
|
|
809
|
+
... [${omitted} characters of log output omitted to fit the model's context] ...
|
|
810
|
+
|
|
811
|
+
${tail}`;
|
|
812
|
+
}
|
|
785
813
|
function resolveExistingPathPrefix(candidate) {
|
|
786
814
|
let current = candidate.replace(/(?::\d+)+$/, "").replace(/['"()\[\]`]+$/, "").trim();
|
|
787
815
|
while (current.length > 0) {
|
|
@@ -844,9 +872,15 @@ var require_dist4 = __commonJS({
|
|
|
844
872
|
return;
|
|
845
873
|
}
|
|
846
874
|
if (processedFiles.has(filePath)) return;
|
|
875
|
+
if (context.length >= MAX_CONTEXT_CHARS) return;
|
|
847
876
|
processedFiles.add(filePath);
|
|
848
877
|
try {
|
|
849
|
-
|
|
878
|
+
let content = import_fs2.default.readFileSync(filePath, "utf-8");
|
|
879
|
+
if (content.length > MAX_FILE_CHARS) {
|
|
880
|
+
const omitted = content.length - MAX_FILE_CHARS;
|
|
881
|
+
content = `${content.slice(0, MAX_FILE_CHARS)}
|
|
882
|
+
... [file truncated: ${omitted} more characters not shown]`;
|
|
883
|
+
}
|
|
850
884
|
context += `
|
|
851
885
|
--- File: ${relPath} ---
|
|
852
886
|
\`\`\`
|
|
@@ -931,10 +965,11 @@ ${w}`).join("\n\n")}
|
|
|
931
965
|
|
|
932
966
|
**CRITICAL RULE:** Do NOT suggest modifying or creating the files listed under "Previous Failed Attempts" if they failed with a "File not found" or "Search string not found" error. You must inspect the compiler error logs below to find the actual file that exists and contains the error.`;
|
|
933
967
|
}
|
|
968
|
+
compilerLogs = truncateLogs(compilerLogs);
|
|
934
969
|
const contextSection = getContextFiles(compilerLogs, cwd);
|
|
935
970
|
return `You are an expert software engineer specialising in fixing build, lint, and test failures.
|
|
936
971
|
|
|
937
|
-
A project located at "${cwd}" failed to build. Here is the
|
|
972
|
+
A project located at "${cwd}" failed to build. Here is the error output (very long output is shortened in the middle):
|
|
938
973
|
|
|
939
974
|
\`\`\`
|
|
940
975
|
${compilerLogs}
|
|
@@ -1216,6 +1251,7 @@ var require_dist6 = __commonJS({
|
|
|
1216
1251
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
1217
1252
|
var index_exports = {};
|
|
1218
1253
|
__export(index_exports, {
|
|
1254
|
+
runRepairWorkflow: () => runRepairWorkflow,
|
|
1219
1255
|
workflow: () => workflow
|
|
1220
1256
|
});
|
|
1221
1257
|
module2.exports = __toCommonJS(index_exports);
|
|
@@ -1373,6 +1409,12 @@ Any other files from that same suggestion were rolled back to keep the change at
|
|
|
1373
1409
|
return "analyze";
|
|
1374
1410
|
}
|
|
1375
1411
|
var workflow = new import_langgraph2.StateGraph(GraphState).addNode("analyze", analyzeNode).addNode("apply_fix", applyFixNode).addNode("verify", verifyNode).addEdge(import_langgraph2.START, "analyze").addEdge("analyze", "apply_fix").addEdge("apply_fix", "verify").addConditionalEdges("verify", shouldRetry).compile();
|
|
1412
|
+
function runRepairWorkflow(input) {
|
|
1413
|
+
return workflow.invoke(
|
|
1414
|
+
{ ...input, attempts: 0, success: false },
|
|
1415
|
+
{ recursionLimit: input.maxAttempts * 3 + 5 }
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1376
1418
|
}
|
|
1377
1419
|
});
|
|
1378
1420
|
|
|
@@ -1409,10 +1451,12 @@ var require_dist7 = __commonJS({
|
|
|
1409
1451
|
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
1410
1452
|
var index_exports = {};
|
|
1411
1453
|
__export(index_exports, {
|
|
1454
|
+
DEFAULT_MAX_ATTEMPTS: () => DEFAULT_MAX_ATTEMPTS,
|
|
1412
1455
|
detectFramework: () => detectFramework2,
|
|
1413
1456
|
detectPackageManager: () => import_analyzers2.detectPackageManager,
|
|
1414
1457
|
orchestrate: () => orchestrate2,
|
|
1415
|
-
orchestrateAndFix: () => orchestrateAndFix2
|
|
1458
|
+
orchestrateAndFix: () => orchestrateAndFix2,
|
|
1459
|
+
resolveMaxAttempts: () => resolveMaxAttempts2
|
|
1416
1460
|
});
|
|
1417
1461
|
module2.exports = __toCommonJS(index_exports);
|
|
1418
1462
|
var import_fs2 = __toESM2(require("fs"));
|
|
@@ -1444,12 +1488,32 @@ var require_dist7 = __commonJS({
|
|
|
1444
1488
|
}
|
|
1445
1489
|
var import_analyzers = require_dist2();
|
|
1446
1490
|
var import_agents = require_dist6();
|
|
1491
|
+
var import_fs3 = __toESM2(require("fs"));
|
|
1492
|
+
var import_path3 = __toESM2(require("path"));
|
|
1493
|
+
var import_url = require("url");
|
|
1494
|
+
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
1495
|
+
function resolveMaxAttempts2(value) {
|
|
1496
|
+
const attempts = value ?? DEFAULT_MAX_ATTEMPTS;
|
|
1497
|
+
if (!Number.isInteger(attempts) || attempts < 1) {
|
|
1498
|
+
throw new Error(`--max-attempts must be a whole number of 1 or more (received ${value}).`);
|
|
1499
|
+
}
|
|
1500
|
+
return attempts;
|
|
1501
|
+
}
|
|
1447
1502
|
var import_fs22 = __toESM2(require("fs"));
|
|
1448
1503
|
var import_path22 = __toESM2(require("path"));
|
|
1449
|
-
|
|
1504
|
+
function assertNodeProject(cwd) {
|
|
1505
|
+
if (!import_fs22.default.existsSync(import_path22.default.join(cwd, "package.json"))) {
|
|
1506
|
+
throw new Error(`No package.json found in ${cwd}. Point --path at a Node.js project.`);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1450
1509
|
var import_ai_provider = require_dist3();
|
|
1510
|
+
function statusLabel(result) {
|
|
1511
|
+
if (result.skipped) return "\u23ED\uFE0F Skipped (no script defined)";
|
|
1512
|
+
return result.success ? "\u2705 Passed" : "\u274C Failed";
|
|
1513
|
+
}
|
|
1451
1514
|
async function orchestrate2(options = {}) {
|
|
1452
1515
|
const cwd = options.cwd ?? process.cwd();
|
|
1516
|
+
assertNodeProject(cwd);
|
|
1453
1517
|
const [build, lint, test] = await Promise.all([
|
|
1454
1518
|
(0, import_analyzers.runBuild)(cwd),
|
|
1455
1519
|
(0, import_analyzers.runLint)(cwd),
|
|
@@ -1465,7 +1529,8 @@ var require_dist7 = __commonJS({
|
|
|
1465
1529
|
}
|
|
1466
1530
|
async function orchestrateAndFix2(options = {}) {
|
|
1467
1531
|
const cwd = options.cwd ?? process.cwd();
|
|
1468
|
-
|
|
1532
|
+
assertNodeProject(cwd);
|
|
1533
|
+
const maxAttempts = resolveMaxAttempts2(options.maxAttempts);
|
|
1469
1534
|
console.log(`[BugZero] Running validation pipeline in: ${cwd}`);
|
|
1470
1535
|
const pipelineResult = await (0, import_analyzers.runValidationPipeline)(cwd);
|
|
1471
1536
|
if (pipelineResult.success) {
|
|
@@ -1496,12 +1561,10 @@ var require_dist7 = __commonJS({
|
|
|
1496
1561
|
error: "Dry-run: analysis complete, no files modified."
|
|
1497
1562
|
};
|
|
1498
1563
|
}
|
|
1499
|
-
const finalState = await import_agents.
|
|
1564
|
+
const finalState = await (0, import_agents.runRepairWorkflow)({
|
|
1500
1565
|
cwd,
|
|
1501
1566
|
logs: pipelineResult.output,
|
|
1502
|
-
maxAttempts
|
|
1503
|
-
attempts: 0,
|
|
1504
|
-
success: false
|
|
1567
|
+
maxAttempts
|
|
1505
1568
|
});
|
|
1506
1569
|
const result = {
|
|
1507
1570
|
success: finalState.success,
|
|
@@ -1597,9 +1660,9 @@ Generate the Markdown report directly. Do not wrap it in markdown block fences (
|
|
|
1597
1660
|
**Framework:** \`${detectFramework2(cwd)}\`
|
|
1598
1661
|
|
|
1599
1662
|
## \u{1F4CA} Status Summary
|
|
1600
|
-
- **Build:** ${build
|
|
1601
|
-
- **Lint:** ${lint
|
|
1602
|
-
- **Test:** ${test
|
|
1663
|
+
- **Build:** ${statusLabel(build)}
|
|
1664
|
+
- **Lint:** ${statusLabel(lint)}
|
|
1665
|
+
- **Test:** ${statusLabel(test)}
|
|
1603
1666
|
|
|
1604
1667
|
## \u274C Failed Checks & Error Output
|
|
1605
1668
|
${logs}
|
|
@@ -1618,9 +1681,9 @@ ${logs}
|
|
|
1618
1681
|
**Framework:** \`${detectFramework2(cwd)}\`
|
|
1619
1682
|
|
|
1620
1683
|
## \u{1F4CA} Status Summary
|
|
1621
|
-
- **Build:**
|
|
1622
|
-
- **Lint:**
|
|
1623
|
-
- **Test:**
|
|
1684
|
+
- **Build:** ${statusLabel(build)}
|
|
1685
|
+
- **Lint:** ${statusLabel(lint)}
|
|
1686
|
+
- **Test:** ${statusLabel(test)}
|
|
1624
1687
|
|
|
1625
1688
|
\u{1F389} **All checks passed! Your project is in perfect shape.**`;
|
|
1626
1689
|
}
|
|
@@ -1725,9 +1788,9 @@ ${rawOutput}
|
|
|
1725
1788
|
|
|
1726
1789
|
---
|
|
1727
1790
|
*Report generated by **BugZero** on ${(/* @__PURE__ */ new Date()).toLocaleString()}*`;
|
|
1728
|
-
const reportPath =
|
|
1791
|
+
const reportPath = import_path3.default.resolve(cwd, "bugzero-report.md");
|
|
1729
1792
|
try {
|
|
1730
|
-
|
|
1793
|
+
import_fs3.default.writeFileSync(reportPath, content, "utf-8");
|
|
1731
1794
|
const clickableUrl = (0, import_url.pathToFileURL)(reportPath).toString();
|
|
1732
1795
|
console.log(`
|
|
1733
1796
|
\u{1F4DD} Generated report successfully!
|
|
@@ -1769,9 +1832,10 @@ program.command("hunt").description("Run build, lint, and tests \u2014 report is
|
|
|
1769
1832
|
`);
|
|
1770
1833
|
const { build, lint, test } = await (0, import_core.orchestrate)({ cwd });
|
|
1771
1834
|
console.log("\u2500\u2500 Pipeline Summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1772
|
-
|
|
1773
|
-
console.log(`
|
|
1774
|
-
console.log(`
|
|
1835
|
+
const label = (r) => r.skipped ? "\u23ED\uFE0F Skipped (no script)" : r.success ? "\u2705 Passed" : "\u274C Failed (see report)";
|
|
1836
|
+
console.log(` Build: ${label(build)}`);
|
|
1837
|
+
console.log(` Lint: ${label(lint)}`);
|
|
1838
|
+
console.log(` Tests: ${label(test)}`);
|
|
1775
1839
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1776
1840
|
const allPassed = build.success && lint.success && test.success;
|
|
1777
1841
|
console.log(`
|
|
@@ -1787,7 +1851,7 @@ ${allPassed ? "\u2705 All checks passed" : "\u274C Issues found \u2014 run 'bugz
|
|
|
1787
1851
|
program.command("rescue").description("Detect build failures and automatically apply AI-generated fixes").option("-p, --path <dir>", "Path to the target project", ".").option("-n, --max-attempts <number>", "Maximum AI fix attempts", "3").option("--dry-run", "Analyse only \u2014 print what would be fixed without writing files", false).action(async (opts) => {
|
|
1788
1852
|
try {
|
|
1789
1853
|
const cwd = import_path.default.resolve(opts.path);
|
|
1790
|
-
const maxAttempts =
|
|
1854
|
+
const maxAttempts = (0, import_core.resolveMaxAttempts)(Number(opts.maxAttempts));
|
|
1791
1855
|
const dryRun = opts.dryRun;
|
|
1792
1856
|
const framework = (0, import_core.detectFramework)(cwd);
|
|
1793
1857
|
const packageManager = (0, import_core.detectPackageManager)(cwd);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bugzero",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"description": "Autonomous AI-powered CLI and GitHub Action that detects build, lint, and test failures, generates multi-file patches, applies them atomically with fuzzy matching, and re-verifies until your project is green.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Saksham Agarwal (https://github.com/Saksham1800t)",
|