autopilot-code 0.0.11 → 0.0.13

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/cli.js CHANGED
@@ -209,7 +209,7 @@ function installSystemdService() {
209
209
  if (!systemctl("enable", ["autopilot.service", ...daemonReloadArgs])) {
210
210
  process.exit(1);
211
211
  }
212
- if (!systemctl("start", ["autopilot.service", ...daemonReloadArgs])) {
212
+ if (!systemctl("restart", ["autopilot.service", ...daemonReloadArgs])) {
213
213
  process.exit(1);
214
214
  }
215
215
  console.log("✅ Autopilot service installed, enabled and started.");
@@ -385,7 +385,7 @@ program
385
385
  .command("scan")
386
386
  .description("Discover autopilot-enabled repos + show next issue candidate (dry-run)")
387
387
  .option("--root <paths...>", "Root folder(s) that contain git repos (space-separated)")
388
- .option("--max-depth <number>", "Maximum depth for recursive repo discovery", "5")
388
+ .option("--max-depth <number>", "Maximum depth for recursive repo discovery", "3")
389
389
  .option("--min-priority <label>", "Minimum priority label to work (e.g. p0, p1)")
390
390
  .option("--ignore-labels <labels...>", "Ignore issues with these labels (space-separated)")
391
391
  .action((opts) => {
@@ -402,7 +402,7 @@ program
402
402
  console.log("No source folders configured. Run 'autopilot init' to add some.");
403
403
  return;
404
404
  }
405
- const args = [runnerPath, "--root", ...rootPaths];
405
+ const args = ["-u", runnerPath, "--root", ...rootPaths];
406
406
  if (opts.maxDepth)
407
407
  args.push("--max-depth", opts.maxDepth);
408
408
  if (opts.minPriority)
@@ -417,7 +417,7 @@ program
417
417
  .command("run-once")
418
418
  .description("Claim exactly one issue and post a progress comment")
419
419
  .option("--root <paths...>", "Root folder(s) that contain git repos (space-separated)")
420
- .option("--max-depth <number>", "Maximum depth for recursive repo discovery", "5")
420
+ .option("--max-depth <number>", "Maximum depth for recursive repo discovery", "3")
421
421
  .option("--min-priority <label>", "Minimum priority label to work (e.g. p0, p1)")
422
422
  .option("--ignore-labels <labels...>", "Ignore issues with these labels (space-separated)")
423
423
  .action((opts) => {
@@ -434,7 +434,7 @@ program
434
434
  console.log("No source folders configured. Run 'autopilot init' to add some.");
435
435
  return;
436
436
  }
437
- const args = [runnerPath, "--root", ...rootPaths];
437
+ const args = ["-u", runnerPath, "--root", ...rootPaths];
438
438
  if (opts.maxDepth)
439
439
  args.push("--max-depth", opts.maxDepth);
440
440
  if (opts.minPriority)
@@ -450,7 +450,7 @@ program
450
450
  .option("--foreground", "Run in foreground mode (log to stdout)")
451
451
  .option("--interval-seconds <number>", "Interval between cycles in seconds", "60")
452
452
  .option("--root <paths...>", "Root folder(s) that contain git repos (space-separated)")
453
- .option("--max-depth <number>", "Maximum depth for recursive repo discovery", "5")
453
+ .option("--max-depth <number>", "Maximum depth for recursive repo discovery", "3")
454
454
  .option("--min-priority <label>", "Minimum priority label to work (e.g. p0, p1)")
455
455
  .option("--ignore-labels <labels...>", "Ignore issues with these labels (space-separated)")
456
456
  .action((opts) => {
@@ -467,7 +467,7 @@ program
467
467
  console.log("No source folders configured. Run 'autopilot init' to add some.");
468
468
  return;
469
469
  }
470
- const args = [runnerPath, "--root", ...rootPaths];
470
+ const args = ["-u", runnerPath, "--root", ...rootPaths];
471
471
  if (opts.maxDepth)
472
472
  args.push("--max-depth", opts.maxDepth);
473
473
  if (opts.minPriority)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autopilot-code",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "private": false,
5
5
  "description": "Repo-issue–driven autopilot runner",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@ from typing import Any
28
28
  STATE_DIR = ".autopilot"
29
29
  STATE_FILE = "state.json"
30
30
  DEFAULT_HEARTBEAT_MAX_AGE_SECS = 60 * 60 # 1h
31
- DEFAULT_MAX_DEPTH = 5
31
+ DEFAULT_MAX_DEPTH = 3
32
32
  IGNORED_DIRS = {
33
33
  "node_modules",
34
34
  ".venv",
@@ -100,10 +100,8 @@ def load_config(repo_root: Path) -> RepoConfig | None:
100
100
  allowed_merge_users = list(data.get("allowedMergeUsers", []))
101
101
 
102
102
  if auto_merge and not allowed_merge_users:
103
- raise RuntimeError(
104
- "autoMerge is enabled but allowedMergeUsers list is empty or missing. "
105
- "Please specify at least one allowed GitHub username."
106
- )
103
+ print(f"Warning: [{data.get('repo', 'unknown')}] autoMerge is enabled but allowedMergeUsers is empty. Disabling autoMerge for this repo.", flush=True)
104
+ auto_merge = False
107
105
 
108
106
  auto_resolve_conflicts = data.get("autoResolveConflicts", True)
109
107
  conflict_resolution_max_attempts = int(data.get("conflictResolutionMaxAttempts", 3))
@@ -148,13 +146,16 @@ def _discover_repos_recursive(
148
146
  if current_depth > max_depth:
149
147
  return
150
148
 
151
- # Check if current directory is a git repo with autopilot config
152
- if (current_dir / ".git").exists() and (
153
- current_dir / ".autopilot" / "autopilot.json"
154
- ).exists():
155
- cfg = load_config(current_dir)
156
- if cfg:
157
- out.append(cfg)
149
+ # Check if current directory is a git repo
150
+ if (current_dir / ".git").exists():
151
+ if (current_dir / ".autopilot" / "autopilot.json").exists():
152
+ try:
153
+ cfg = load_config(current_dir)
154
+ if cfg:
155
+ out.append(cfg)
156
+ except Exception as e:
157
+ print(f"Error loading config in {current_dir}: {e}", flush=True)
158
+ # stop descending once we hit a git repo
158
159
  return
159
160
 
160
161
  # Recursively search subdirectories (depth-first)
@@ -162,7 +163,7 @@ def _discover_repos_recursive(
162
163
  for child in sorted(current_dir.iterdir(), key=lambda p: p.name.lower()):
163
164
  if not child.is_dir():
164
165
  continue
165
- if child.name in IGNORED_DIRS:
166
+ if child.name in IGNORED_DIRS or child.name.startswith("."):
166
167
  continue
167
168
  _discover_repos_recursive(child, current_depth + 1, max_depth, out)
168
169
  except PermissionError:
@@ -356,6 +357,7 @@ def run_cycle(
356
357
  claimed_count = 0
357
358
 
358
359
  for cfg in all_configs:
360
+ print(f"[{cfg.repo}] Scanning for issues...", flush=True)
359
361
  # 1) First, check any in-progress issues and mark blocked if stale.
360
362
  inprog = list_in_progress_issues(cfg)
361
363
  for it in inprog:
@@ -391,7 +393,7 @@ def run_cycle(
391
393
  "(Durable tracking: this repo will maintain `.autopilot/state.json` as a heartbeat; "
392
394
  "the runner does not inspect processes.)"
393
395
  )
394
- print(f"[{cfg.repo}] next issue: #{issue['number']} {issue['title']}")
396
+ print(f"[{cfg.repo}] next issue: #{issue['number']} {issue['title']}", flush=True)
395
397
  if dry_run:
396
398
  claimed_count += 1
397
399
  continue
@@ -441,10 +443,10 @@ def main() -> int:
441
443
  for root_str in args.root:
442
444
  root = Path(root_str).resolve()
443
445
  if not root.exists():
444
- print(f"Warning: root path {root} does not exist, skipping")
446
+ print(f"Warning: root path {root} does not exist, skipping", flush=True)
445
447
  continue
446
448
  if not root.is_dir():
447
- print(f"Warning: root path {root} is not a directory, skipping")
449
+ print(f"Warning: root path {root} is not a directory, skipping", flush=True)
448
450
  continue
449
451
  configs = discover_repos(root, max_depth=args.max_depth)
450
452
 
@@ -458,12 +460,12 @@ def main() -> int:
458
460
  all_configs.extend(configs)
459
461
 
460
462
  if not all_configs:
461
- print("No autopilot-enabled repos found.")
463
+ print("No autopilot-enabled repos found.", flush=True)
462
464
  return 0
463
465
 
464
- print(f"Found {len(all_configs)} autopilot-enabled repo(s)")
466
+ print(f"Found {len(all_configs)} autopilot-enabled repo(s)", flush=True)
465
467
  for cfg in all_configs:
466
- print(f" - {cfg.repo} at {cfg.root}")
468
+ print(f" - {cfg.repo} at {cfg.root}", flush=True)
467
469
 
468
470
  # Loop mode (for foreground service)
469
471
  if args.interval_seconds is not None:
@@ -471,37 +473,37 @@ def main() -> int:
471
473
 
472
474
  def signal_handler(signum: int, frame: Any) -> None:
473
475
  nonlocal shutdown_requested
474
- print("\nShutdown requested (Ctrl+C), finishing current cycle...")
476
+ print("\nShutdown requested (Ctrl+C), finishing current cycle...", flush=True)
475
477
  shutdown_requested = True
476
478
 
477
479
  signal.signal(signal.SIGINT, signal_handler)
478
480
  signal.signal(signal.SIGTERM, signal_handler)
479
481
 
480
- print(f"Running in foreground mode with {args.interval_seconds}s interval")
481
- print("Press Ctrl+C to shut down cleanly\n")
482
+ print(f"Running in foreground mode with {args.interval_seconds}s interval", flush=True)
483
+ print("Press Ctrl+C to shut down cleanly\n", flush=True)
482
484
 
483
485
  cycle_num = 0
484
486
  while not shutdown_requested:
485
487
  cycle_num += 1
486
488
  timestamp = time.strftime("%Y-%m-%d %H:%M:%S %Z")
487
- print(f"\n=== Cycle {cycle_num} at {timestamp} ===")
489
+ print(f"\n=== Cycle {cycle_num} at {timestamp} ===", flush=True)
488
490
 
489
491
  try:
490
492
  claimed = run_cycle(all_configs, dry_run=args.dry_run)
491
493
  if claimed == 0:
492
- print("No issues claimed in this cycle")
494
+ print("No issues claimed in this cycle", flush=True)
493
495
  else:
494
- print(f"Claimed {claimed} issue(s) in this cycle")
496
+ print(f"Claimed {claimed} issue(s) in this cycle", flush=True)
495
497
  except Exception as e:
496
- print(f"Error in cycle {cycle_num}: {e}")
498
+ print(f"Error in cycle {cycle_num}: {e}", flush=True)
497
499
 
498
500
  if shutdown_requested:
499
501
  break
500
502
 
501
- print(f"Sleeping for {args.interval_seconds}s...")
503
+ print(f"Sleeping for {args.interval_seconds}s...", flush=True)
502
504
  time.sleep(args.interval_seconds)
503
505
 
504
- print("\nShutdown complete")
506
+ print("\nShutdown complete", flush=True)
505
507
  return 0
506
508
 
507
509
  # Single-shot mode (run-once)