@neriros/ralphy 2.13.2 → 2.13.4

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 (2) hide show
  1. package/dist/cli/index.js +184 -33
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -56407,7 +56407,7 @@ function log(msg) {
56407
56407
  // package.json
56408
56408
  var package_default = {
56409
56409
  name: "@neriros/ralphy",
56410
- version: "2.13.2",
56410
+ version: "2.13.4",
56411
56411
  description: "An iterative AI task execution framework. Orchestrates multi-phase autonomous work using Claude or Codex engines.",
56412
56412
  keywords: [
56413
56413
  "agent",
@@ -56653,8 +56653,6 @@ async function parseArgs(argv) {
56653
56653
  let expectMaxRuntime = false;
56654
56654
  let expectMaxFailures = false;
56655
56655
  let expectMaxIterations = false;
56656
- let expectTimeout = false;
56657
- let expectPushInterval = false;
56658
56656
  let expectLinearTeam = false;
56659
56657
  let expectLinearAssignee = false;
56660
56658
  let expectPollInterval = false;
@@ -56717,14 +56715,6 @@ async function parseArgs(argv) {
56717
56715
  expectMaxIterations = false;
56718
56716
  continue;
56719
56717
  }
56720
- if (expectTimeout) {
56721
- expectTimeout = false;
56722
- continue;
56723
- }
56724
- if (expectPushInterval) {
56725
- expectPushInterval = false;
56726
- continue;
56727
- }
56728
56718
  if (expectLinearTeam) {
56729
56719
  result2.linearTeam = arg;
56730
56720
  expectLinearTeam = false;
@@ -56794,12 +56784,6 @@ async function parseArgs(argv) {
56794
56784
  case "--max-iterations":
56795
56785
  expectMaxIterations = true;
56796
56786
  break;
56797
- case "--timeout":
56798
- expectTimeout = true;
56799
- break;
56800
- case "--push-interval":
56801
- expectPushInterval = true;
56802
- break;
56803
56787
  case "--unlimited":
56804
56788
  result2.maxIterations = 0;
56805
56789
  break;
@@ -69479,6 +69463,10 @@ var HOST = "https://eu.i.posthog.com";
69479
69463
  var enabled = process.env["RALPH_TELEMETRY"] !== "0";
69480
69464
  var client = null;
69481
69465
  var distinctId = "anonymous";
69466
+ var defaultProps = {};
69467
+ function setDefaultProperties(props) {
69468
+ defaultProps = { ...defaultProps, ...props };
69469
+ }
69482
69470
  async function init() {
69483
69471
  if (!enabled)
69484
69472
  return;
@@ -69497,7 +69485,8 @@ async function init() {
69497
69485
  });
69498
69486
  }
69499
69487
  function capture(event, properties) {
69500
- client?.capture({ distinctId, event, ...properties !== undefined && { properties } });
69488
+ const merged = { ...defaultProps, ...properties };
69489
+ client?.capture({ distinctId, event, properties: merged });
69501
69490
  }
69502
69491
  async function shutdown() {
69503
69492
  if (client)
@@ -69889,10 +69878,16 @@ function useLoop(opts) {
69889
69878
  const result2 = `failed:exit-${engineResult.exitCode}`;
69890
69879
  updateStateIteration(stateDir, result2, iterStart, opts.engine, opts.model, engineResult.usage);
69891
69880
  if (failure.shouldStop || engineResult.rateLimited) {
69881
+ capture("engine_rate_limited", { exit_code: engineResult.exitCode, iteration: iter });
69892
69882
  finalStopReason = "rateLimited";
69893
69883
  setStopReason("rateLimited");
69894
69884
  break;
69895
69885
  }
69886
+ capture("iteration_failed", {
69887
+ exit_code: engineResult.exitCode,
69888
+ iteration: iter,
69889
+ consecutive_failures: consFailures + 1
69890
+ });
69896
69891
  if (result2 === lastResult) {
69897
69892
  consFailures++;
69898
69893
  } else {
@@ -69921,7 +69916,9 @@ function useLoop(opts) {
69921
69916
  await sleep(opts.delay);
69922
69917
  }
69923
69918
  } catch (err) {
69919
+ const message = err instanceof Error ? err.message : String(err);
69924
69920
  addInfo(`Engine error: ${err}`);
69921
+ capture("engine_error", { iteration: iter, error: message });
69925
69922
  break;
69926
69923
  }
69927
69924
  }
@@ -70206,23 +70203,145 @@ var RalphyConfigSchema = exports_external.object({
70206
70203
  model: "opus",
70207
70204
  linear: { postComments: true, updateEveryIterations: 10, indicators: {} }
70208
70205
  });
70206
+ function stripJsonComments(text) {
70207
+ return text.replace(/\/\/[^\n]*/g, "");
70208
+ }
70209
70209
  async function loadRalphyConfig(projectRoot) {
70210
70210
  const path = join10(projectRoot, "ralphy.config.json");
70211
70211
  const file = Bun.file(path);
70212
70212
  if (!await file.exists()) {
70213
70213
  return RalphyConfigSchema.parse({});
70214
70214
  }
70215
- const raw = await file.json();
70215
+ const text = await file.text();
70216
+ const raw = JSON.parse(stripJsonComments(text));
70216
70217
  return RalphyConfigSchema.parse(raw);
70217
70218
  }
70219
+ var DEFAULT_CONFIG_TEMPLATE = `{
70220
+ // How many tasks to run in parallel.
70221
+ "concurrency": 1,
70222
+
70223
+ // Seconds between polls for new Linear issues (agent mode).
70224
+ "pollIntervalSeconds": 60,
70225
+
70226
+ // Maximum iterations per task. 0 = unlimited.
70227
+ "maxIterationsPerTask": 0,
70228
+
70229
+ // Maximum cost in USD per task. 0 = unlimited.
70230
+ "maxCostUsdPerTask": 0,
70231
+
70232
+ // Maximum wall-clock minutes per task. 0 = unlimited.
70233
+ "maxRuntimeMinutesPerTask": 0,
70234
+
70235
+ // Stop a task after this many consecutive identical failures.
70236
+ "maxConsecutiveFailuresPerTask": 5,
70237
+
70238
+ // Seconds to wait between loop iterations (throttle).
70239
+ "iterationDelaySeconds": 0,
70240
+
70241
+ // Log the raw engine stream to stdout.
70242
+ "logRawStream": false,
70243
+
70244
+ // Pass --verbose to the ralph task sub-process.
70245
+ "taskVerbose": false,
70246
+
70247
+ // Run each task in an isolated git worktree.
70248
+ "useWorktree": false,
70249
+
70250
+ // Delete the worktree after a successful task.
70251
+ "cleanupWorktreeOnSuccess": false,
70252
+
70253
+ // Shell script to run inside the worktree before the task starts.
70254
+ // "setupScript": "bun install",
70255
+
70256
+ // Shell script to run inside the worktree after the task finishes.
70257
+ // "teardownScript": "bun run lint",
70258
+
70259
+ // Extra text appended to every task prompt.
70260
+ // "appendPrompt": "Always run tests before finishing.",
70261
+
70262
+ // Open a pull request after a task succeeds.
70263
+ "createPrOnSuccess": false,
70264
+
70265
+ // Base branch for pull requests.
70266
+ "prBaseBranch": "main",
70267
+
70268
+ // Let the agent attempt to fix CI failures after a PR is created.
70269
+ "fixCiOnFailure": false,
70270
+
70271
+ // Maximum number of CI-fix attempts per task.
70272
+ "maxCiFixAttempts": 5,
70273
+
70274
+ // Seconds between CI status polls.
70275
+ "ciPollIntervalSeconds": 30,
70276
+
70277
+ // Underlying engine: "claude" or "codex".
70278
+ "engine": "claude",
70279
+
70280
+ // Model tier: "haiku", "sonnet", or "opus".
70281
+ "model": "opus",
70282
+
70283
+ "linear": {
70284
+ // Linear team key to filter issues (e.g. "ENG"). Omit to match all teams.
70285
+ // "team": "ENG",
70286
+
70287
+ // Linear user to filter issues. Can be an email address or user ID.
70288
+ // Omit to match issues regardless of assignee.
70289
+ // "assignee": "dev@example.com",
70290
+
70291
+ // Post progress comments on the Linear issue while a task is running.
70292
+ "postComments": true,
70293
+
70294
+ // Post a progress update every N iterations. 0 disables. Requires postComments.
70295
+ "updateEveryIterations": 10,
70296
+
70297
+ // ---------------------------------------------------------------------------
70298
+ // Linear indicators \u2014 COMMENTED OUT BY DEFAULT
70299
+ //
70300
+ // Indicators map Ralph lifecycle events to Linear labels/statuses.
70301
+ // WARNING: Activating indicators will query AND mutate your Linear workspace.
70302
+ // Labels or statuses that do not already exist may be created automatically.
70303
+ // Review every value against your actual Linear workspace before enabling,
70304
+ // then replace the empty object below with the full indicators block.
70305
+ //
70306
+ // To activate, replace "indicators": {} with:
70307
+ //
70308
+ // "indicators": {
70309
+ // // Issues to pick up (any-of filter \u2014 Ralph will start working on these).
70310
+ // "getTodo": { "filter": [{ "type": "status", "value": "Todo" }] },
70311
+ //
70312
+ // // Issues already in flight (resume after restart).
70313
+ // "getInProgress": { "filter": [{ "type": "label", "value": "ralph:in-progress" }] },
70314
+ //
70315
+ // // Issues whose PR has a merge conflict (Ralph will attempt a re-fix run).
70316
+ // "getConflicted": { "filter": [{ "type": "label", "value": "ralph:conflict" }] },
70317
+ //
70318
+ // // Applied when Ralph picks up an issue.
70319
+ // "setInProgress": { "type": "label", "value": "ralph:in-progress" },
70320
+ //
70321
+ // // Applied on clean success.
70322
+ // "setDone": { "type": "status", "value": "In Review" },
70323
+ //
70324
+ // // Applied when the task exits with an error (quarantine signal).
70325
+ // "setError": { "type": "label", "value": "ralph:error" },
70326
+ //
70327
+ // // Applied when a PR merge conflict is detected.
70328
+ // "setConflicted": { "type": "label", "value": "ralph:conflict" },
70329
+ //
70330
+ // // Label-only marker(s) removed once the conflict is fixed.
70331
+ // // Note: only label-typed markers are valid here \u2014 status removal is not supported.
70332
+ // "clearConflicted": { "type": "label", "value": "ralph:conflict" }
70333
+ // }
70334
+ // ---------------------------------------------------------------------------
70335
+ "indicators": {}
70336
+ }
70337
+ }
70338
+ `;
70218
70339
  async function ensureRalphyConfig(projectRoot) {
70219
70340
  const path = join10(projectRoot, "ralphy.config.json");
70220
70341
  const file = Bun.file(path);
70221
70342
  if (await file.exists())
70222
70343
  return path;
70223
- const defaults2 = RalphyConfigSchema.parse({});
70224
- await Bun.write(path, JSON.stringify(defaults2, null, 2) + `
70225
- `);
70344
+ await Bun.write(path, DEFAULT_CONFIG_TEMPLATE);
70226
70345
  return path;
70227
70346
  }
70228
70347
 
@@ -70469,6 +70588,7 @@ class AgentCoordinator {
70469
70588
  ]);
70470
70589
  } catch (err) {
70471
70590
  this.deps.onLog(`! Linear poll failed: ${err.message}`, "red");
70591
+ capture("agent_linear_poll_failed", { error: err.message });
70472
70592
  return { found: 0, added: 0 };
70473
70593
  }
70474
70594
  const queuedIds = new Set(this.queue.map((q) => q.issue.id));
@@ -70593,10 +70713,16 @@ class AgentCoordinator {
70593
70713
  const alreadyNotified = this.conflictNotified.has(issue.id);
70594
70714
  if (alreadyNotified)
70595
70715
  continue;
70716
+ capture("agent_conflict_detected", { issue_identifier: issue.identifier });
70596
70717
  try {
70597
70718
  await this.deps.applyIndicator(issue, this.opts.setConflicted);
70598
70719
  } catch (err) {
70599
70720
  this.deps.onLog(`! Linear setConflicted failed for ${issue.identifier}: ${err.message}`, "red");
70721
+ capture("agent_indicator_failed", {
70722
+ indicator: "setConflicted",
70723
+ issue_identifier: issue.identifier,
70724
+ error: err.message
70725
+ });
70600
70726
  continue;
70601
70727
  }
70602
70728
  this.conflictNotified.add(issue.id);
@@ -70627,6 +70753,11 @@ class AgentCoordinator {
70627
70753
  } catch (err) {
70628
70754
  this.pendingIds.delete(issue.id);
70629
70755
  this.deps.onLog(`! prepare(${mode}) failed for ${issue.identifier}: ${err.message}`, "red");
70756
+ capture("agent_prepare_failed", {
70757
+ spawn_mode: mode,
70758
+ issue_identifier: issue.identifier,
70759
+ error: err.message
70760
+ });
70630
70761
  this.spawnNext();
70631
70762
  return;
70632
70763
  }
@@ -70639,6 +70770,11 @@ class AgentCoordinator {
70639
70770
  await this.deps.applyIndicator(issue, this.opts.setInProgress);
70640
70771
  } catch (err) {
70641
70772
  this.deps.onLog(`! Linear setInProgress failed for ${issue.identifier}: ${err.message}`, "yellow");
70773
+ capture("agent_indicator_failed", {
70774
+ indicator: "setInProgress",
70775
+ issue_identifier: issue.identifier,
70776
+ error: err.message
70777
+ });
70642
70778
  }
70643
70779
  }
70644
70780
  if (mode === "fresh" && this.opts.postComments !== false) {
@@ -70670,6 +70806,10 @@ class AgentCoordinator {
70670
70806
  };
70671
70807
  this.workers.push(worker);
70672
70808
  this.pendingIds.delete(issue.id);
70809
+ capture("agent_worker_spawned", {
70810
+ spawn_mode: mode,
70811
+ issue_identifier: issue.identifier
70812
+ });
70673
70813
  this.deps.onWorkersChanged();
70674
70814
  handle.exited.then(async (code) => {
70675
70815
  const idx = this.workers.indexOf(worker);
@@ -70677,6 +70817,12 @@ class AgentCoordinator {
70677
70817
  this.workers.splice(idx, 1);
70678
70818
  const ok = code === 0;
70679
70819
  this.deps.onLog(`${ok ? "\u2713" : "\u2717"} ${issue.identifier} \u2192 ${prep.changeName} exited (code ${code})`, ok ? "green" : "red");
70820
+ capture("agent_worker_exited", {
70821
+ spawn_mode: mode,
70822
+ issue_identifier: issue.identifier,
70823
+ exit_code: code,
70824
+ ok
70825
+ });
70680
70826
  await this.notifyExited(issue, prep.changeName, code, mode);
70681
70827
  this.deps.onWorkersChanged();
70682
70828
  this.spawnNext();
@@ -70701,6 +70847,11 @@ class AgentCoordinator {
70701
70847
  await this.deps.removeIndicator(issue, this.opts.clearConflicted);
70702
70848
  } catch (err) {
70703
70849
  this.deps.onLog(`! Linear clearConflicted failed for ${issue.identifier}: ${err.message}`, "red");
70850
+ capture("agent_indicator_failed", {
70851
+ indicator: "clearConflicted",
70852
+ issue_identifier: issue.identifier,
70853
+ error: err.message
70854
+ });
70704
70855
  }
70705
70856
  }
70706
70857
  this.conflictNotified.delete(issue.id);
@@ -70709,6 +70860,11 @@ class AgentCoordinator {
70709
70860
  await this.deps.applyIndicator(issue, this.opts.setDone);
70710
70861
  } catch (err) {
70711
70862
  this.deps.onLog(`! Linear setDone failed for ${issue.identifier}: ${err.message}`, "red");
70863
+ capture("agent_indicator_failed", {
70864
+ indicator: "setDone",
70865
+ issue_identifier: issue.identifier,
70866
+ error: err.message
70867
+ });
70712
70868
  }
70713
70869
  }
70714
70870
  } else if (this.opts.setError) {
@@ -70716,6 +70872,11 @@ class AgentCoordinator {
70716
70872
  await this.deps.applyIndicator(issue, this.opts.setError);
70717
70873
  } catch (err) {
70718
70874
  this.deps.onLog(`! Linear setError failed for ${issue.identifier}: ${err.message}`, "red");
70875
+ capture("agent_indicator_failed", {
70876
+ indicator: "setError",
70877
+ issue_identifier: issue.identifier,
70878
+ error: err.message
70879
+ });
70719
70880
  }
70720
70881
  }
70721
70882
  }
@@ -71892,17 +72053,6 @@ PR: ${prUrl}` : ""
71892
72053
  postComments: cfg.linear.postComments,
71893
72054
  commentEveryIterations: cfg.linear.updateEveryIterations
71894
72055
  });
71895
- (async () => {
71896
- const legacy = Bun.file(projectLayout(projectRoot).agentStateFile);
71897
- if (await legacy.exists()) {
71898
- onLog(" legacy .ralph/agent-state.json detected \u2014 Linear is now the source of truth; deleting", "gray");
71899
- try {
71900
- await legacy.delete();
71901
- } catch (err) {
71902
- onLog(`! failed to delete legacy agent-state.json: ${err.message}`, "yellow");
71903
- }
71904
- }
71905
- })();
71906
72056
  const filterDesc = describeIndicators(indicators, team, assignee);
71907
72057
  return {
71908
72058
  coord,
@@ -72457,6 +72607,7 @@ try {
72457
72607
  printHelp();
72458
72608
  process.exit(1);
72459
72609
  }
72610
+ setDefaultProperties({ mode: args.mode, engine: args.engine, model: args.model });
72460
72611
  capture("command_run", { mode: args.mode, engine: args.engine, model: args.model });
72461
72612
  try {
72462
72613
  const projectRoot = await findProjectRoot();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neriros/ralphy",
3
- "version": "2.13.2",
3
+ "version": "2.13.4",
4
4
  "description": "An iterative AI task execution framework. Orchestrates multi-phase autonomous work using Claude or Codex engines.",
5
5
  "keywords": [
6
6
  "agent",