bugzero 0.0.43 → 0.0.44

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.
Files changed (3) hide show
  1. package/README.md +16 -1
  2. package/dist/index.js +98 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -114,6 +114,7 @@ bugzero rescue
114
114
  ### Integrations and output
115
115
 
116
116
  - **Markdown reports.** Every `hunt` and `rescue` run writes `bugzero-report.md` to the target project: a pass/fail summary of build, lint, and tests, the full error logs, the model used, token usage, and before/after diffs for every file patched. The terminal prints a clickable link straight to it.
117
+ - **JSON output.** Add `--json` to `hunt` or `rescue` to print the result as a single JSON document on stdout, with all human-readable logs moved to stderr and the exit code unchanged (0 on success, 1 otherwise), so scripts and CI can parse it. See [Scripting and CI](#scripting-and-ci).
117
118
  - **GitHub Action mode.** Run the same repair loop in CI. Instead of patching a local checkout, the Action commits every changed file in one atomic commit through the GitHub API and opens a pull request — see [GitHub Action Mode](#github-action-mode) below.
118
119
 
119
120
  ---
@@ -191,7 +192,7 @@ OPENROUTER_API_KEY=your_openrouter_api_key_here
191
192
  ## Commands
192
193
 
193
194
  ### `bugzero hunt`
194
- Run build, lint, and test checks. Reports all failures without modifying any files. Accepts `--timeout <seconds>`, like `rescue`.
195
+ Run build, lint, and test checks. Reports all failures without modifying any files. Accepts `--timeout <seconds>` and `--json`, like `rescue`.
195
196
 
196
197
  ```bash
197
198
  bugzero hunt --path /path/to/your/project
@@ -213,6 +214,7 @@ bugzero rescue --path /path/to/your/project
213
214
  | `--max-attempts <n>` | `-n` | `3` | Maximum AI fix iterations before giving up |
214
215
  | `--timeout <seconds>` | `-t` | none | Stop any build, lint, or test command that runs longer than this many seconds |
215
216
  | `--dry-run` | | `false` | Analyze only — no files will be written |
217
+ | `--json` | | `false` | Print the result as one JSON document on stdout (logs go to stderr) |
216
218
 
217
219
  </details>
218
220
 
@@ -236,6 +238,19 @@ bugzero vibe
236
238
 
237
239
  ---
238
240
 
241
+ ## Scripting and CI
242
+
243
+ `hunt` and `rescue` accept `--json`. Stdout then contains exactly one JSON document and every human-readable log line goes to stderr, so the output is safe to pipe. Exit codes don't change: `0` when everything passes or is fixed, `1` otherwise.
244
+
245
+ ```bash
246
+ bugzero hunt --json | jq '.steps'
247
+ bugzero rescue --json --dry-run | jq -r '.outcome'
248
+ ```
249
+
250
+ `hunt` reports each step (`build`, `lint`, `test`) as `passed`, `failed`, or `skipped`; failed steps include the command's output and whether it timed out. `rescue` reports an `outcome` of `already-passing`, `fixed`, `failed`, or `dry-run`, along with the model, token usage, and the files and root cause of any fix. Both include the path to the generated report. If a run can't start at all (for example, because of an invalid option), stdout is `{ "success": false, "error": "..." }`.
251
+
252
+ ---
253
+
239
254
  ## Configuration
240
255
 
241
256
  BugZero reads a `.bugzerorc` JSON file in your target project directory to pick up model preferences:
package/dist/index.js CHANGED
@@ -393,7 +393,7 @@ var require_dist = __commonJS({
393
393
  while (true) {
394
394
  const envPath = import_path2.default.join(dir, ".env");
395
395
  if (import_fs2.default.existsSync(envPath)) {
396
- import_dotenv.default.config({ path: envPath });
396
+ import_dotenv.default.config({ path: envPath, quiet: true });
397
397
  return;
398
398
  }
399
399
  const parent = import_path2.default.dirname(dir);
@@ -402,7 +402,7 @@ var require_dist = __commonJS({
402
402
  }
403
403
  dir = parent;
404
404
  }
405
- import_dotenv.default.config();
405
+ import_dotenv.default.config({ quiet: true });
406
406
  }
407
407
  loadEnv();
408
408
  var env = {
@@ -1517,6 +1517,7 @@ var require_dist7 = __commonJS({
1517
1517
  var index_exports = {};
1518
1518
  __export(index_exports, {
1519
1519
  DEFAULT_MAX_ATTEMPTS: () => DEFAULT_MAX_ATTEMPTS,
1520
+ REPORT_FILENAME: () => REPORT_FILENAME2,
1520
1521
  detectFramework: () => detectFramework2,
1521
1522
  detectPackageManager: () => import_analyzers2.detectPackageManager,
1522
1523
  orchestrate: () => orchestrate2,
@@ -1625,6 +1626,7 @@ Re-run without \`--dry-run\` to let BugZero attempt a fix.
1625
1626
  }
1626
1627
  }
1627
1628
  var import_ai_provider = require_dist3();
1629
+ var REPORT_FILENAME2 = "bugzero-report.md";
1628
1630
  function statusLabel(result) {
1629
1631
  if (result.skipped) return "\u23ED\uFE0F Skipped (no script defined)";
1630
1632
  return result.success ? "\u2705 Passed" : "\u274C Failed";
@@ -1923,7 +1925,7 @@ ${rawOutput}
1923
1925
 
1924
1926
  ---
1925
1927
  *Report generated by **BugZero** on ${(/* @__PURE__ */ new Date()).toLocaleString()}*`;
1926
- const reportPath = import_path3.default.resolve(cwd, "bugzero-report.md");
1928
+ const reportPath = import_path3.default.resolve(cwd, REPORT_FILENAME2);
1927
1929
  try {
1928
1930
  import_fs3.default.writeFileSync(reportPath, content, "utf-8");
1929
1931
  const clickableUrl = (0, import_url.pathToFileURL)(reportPath).toString();
@@ -1952,6 +1954,62 @@ var import_fs = __toESM(require("fs"));
1952
1954
  var import_path = __toESM(require("path"));
1953
1955
  var import_core = __toESM(require_dist7());
1954
1956
 
1957
+ // src/json-output.ts
1958
+ function stepStatus(step) {
1959
+ if (step.skipped) return "skipped";
1960
+ return step.success ? "passed" : "failed";
1961
+ }
1962
+ function stepJson(step) {
1963
+ const status = stepStatus(step);
1964
+ if (status !== "failed") return { status };
1965
+ return { status, timedOut: step.timedOut === true, output: step.output ?? "" };
1966
+ }
1967
+ function buildHuntJson(info, steps) {
1968
+ return {
1969
+ command: "hunt",
1970
+ success: steps.build.success && steps.lint.success && steps.test.success,
1971
+ path: info.path,
1972
+ framework: info.framework,
1973
+ packageManager: info.packageManager,
1974
+ steps: { build: stepJson(steps.build), lint: stepJson(steps.lint), test: stepJson(steps.test) },
1975
+ reportPath: info.reportPath
1976
+ };
1977
+ }
1978
+ function buildRescueJson(result, info) {
1979
+ let outcome;
1980
+ if (result.success && result.attempts === 0) outcome = "already-passing";
1981
+ else if (result.success) outcome = "fixed";
1982
+ else if (info.dryRun) outcome = "dry-run";
1983
+ else outcome = "failed";
1984
+ const tokens = result.promptTokens !== void 0 && result.completionTokens !== void 0 ? {
1985
+ prompt: result.promptTokens,
1986
+ completion: result.completionTokens,
1987
+ total: result.promptTokens + result.completionTokens
1988
+ } : null;
1989
+ return {
1990
+ command: "rescue",
1991
+ outcome,
1992
+ success: result.success,
1993
+ dryRun: info.dryRun,
1994
+ path: info.path,
1995
+ framework: info.framework,
1996
+ packageManager: info.packageManager,
1997
+ attempts: result.attempts,
1998
+ model: result.modelUsed || null,
1999
+ tokens,
2000
+ fix: result.appliedFix ? {
2001
+ rootCause: result.appliedFix.rootCause,
2002
+ explanation: result.appliedFix.explanation,
2003
+ files: result.appliedFix.patches.map((p) => p.filePath)
2004
+ } : null,
2005
+ error: result.error ?? null,
2006
+ reportPath: info.reportPath
2007
+ };
2008
+ }
2009
+ function buildErrorJson(message) {
2010
+ return { success: false, error: message };
2011
+ }
2012
+
1955
2013
  // src/summary.ts
1956
2014
  function tokenLines(result) {
1957
2015
  if (result.promptTokens === void 0 || result.completionTokens === void 0) return [];
@@ -2011,9 +2069,23 @@ function parseTimeout(raw) {
2011
2069
  (0, import_core.resolveTimeoutMs)(seconds);
2012
2070
  return seconds;
2013
2071
  }
2072
+ var JSON_DESCRIPTION = "Print the result as one JSON document on stdout (human-readable logs go to stderr)";
2073
+ function routeLogsToStderr() {
2074
+ const toStderr = (...args) => console.error(...args);
2075
+ console.log = toStderr;
2076
+ console.info = toStderr;
2077
+ console.debug = toStderr;
2078
+ }
2079
+ function finish(exitCode, json) {
2080
+ if (json === void 0) process.exit(exitCode);
2081
+ process.stdout.write(`${JSON.stringify(json, null, 2)}
2082
+ `, () => process.exit(exitCode));
2083
+ }
2014
2084
  var program = new import_commander.Command();
2015
2085
  program.name("bugzero").description("AI-powered build issue fixer \u2014 detects and repairs build errors automatically").version(version);
2016
- program.command("hunt").description("Run build, lint, and tests \u2014 report issues without modifying files").option("-p, --path <dir>", "Path to the target project", ".").option("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).action(async (opts) => {
2086
+ program.command("hunt").description("Run build, lint, and tests \u2014 report issues without modifying files").option("-p, --path <dir>", "Path to the target project", ".").option("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).option("--json", JSON_DESCRIPTION).action(async (opts) => {
2087
+ const json = opts.json === true;
2088
+ if (json) routeLogsToStderr();
2017
2089
  try {
2018
2090
  const cwd = import_path.default.resolve(opts.path);
2019
2091
  const timeoutSeconds = parseTimeout(opts.timeout);
@@ -2037,14 +2109,22 @@ program.command("hunt").description("Run build, lint, and tests \u2014 report is
2037
2109
  console.log(`
2038
2110
  ${allPassed ? "\u2705 All checks passed" : "\u274C Issues found \u2014 run 'bugzero rescue' to repair"}
2039
2111
  `);
2040
- process.exit(allPassed ? 0 : 1);
2112
+ finish(
2113
+ allPassed ? 0 : 1,
2114
+ json ? buildHuntJson(
2115
+ { path: cwd, framework, packageManager, reportPath: import_path.default.resolve(cwd, import_core.REPORT_FILENAME) },
2116
+ { build, lint, test }
2117
+ ) : void 0
2118
+ );
2041
2119
  } catch (error) {
2042
2120
  console.error(`
2043
2121
  \u274C [BugZero] Execution failed: ${error.message || error}`);
2044
- process.exit(1);
2122
+ finish(1, json ? buildErrorJson(String(error.message || error)) : void 0);
2045
2123
  }
2046
2124
  });
2047
- 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("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).option("--dry-run", "Analyse only \u2014 print what would be fixed without writing files", false).action(async (opts) => {
2125
+ 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("-t, --timeout <seconds>", TIMEOUT_DESCRIPTION).option("--dry-run", "Analyse only \u2014 print what would be fixed without writing files", false).option("--json", JSON_DESCRIPTION).action(async (opts) => {
2126
+ const json = opts.json === true;
2127
+ if (json) routeLogsToStderr();
2048
2128
  try {
2049
2129
  const cwd = import_path.default.resolve(opts.path);
2050
2130
  const maxAttempts = (0, import_core.resolveMaxAttempts)(Number(opts.maxAttempts));
@@ -2066,11 +2146,20 @@ program.command("rescue").description("Detect build failures and automatically a
2066
2146
  const summary = buildRescueSummary(result, { dryRun });
2067
2147
  for (const line of summary.lines) console.log(line);
2068
2148
  console.log();
2069
- process.exit(summary.exitCode);
2149
+ finish(
2150
+ summary.exitCode,
2151
+ json ? buildRescueJson(result, {
2152
+ path: cwd,
2153
+ framework,
2154
+ packageManager,
2155
+ dryRun,
2156
+ reportPath: import_path.default.resolve(cwd, import_core.REPORT_FILENAME)
2157
+ }) : void 0
2158
+ );
2070
2159
  } catch (error) {
2071
2160
  console.error(`
2072
2161
  \u274C [BugZero] Execution failed: ${error.message || error}`);
2073
- process.exit(1);
2162
+ finish(1, json ? buildErrorJson(String(error.message || error)) : void 0);
2074
2163
  }
2075
2164
  });
2076
2165
  program.command("protect").description("[Deprecated] Use 'hunt' instead").action(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bugzero",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
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)",