@neriros/ralphy 3.10.1 → 3.10.3

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/mcp/index.js CHANGED
@@ -24063,6 +24063,7 @@ var HistoryEntrySchema = exports_external.object({
24063
24063
  engine: exports_external.string(),
24064
24064
  model: exports_external.string(),
24065
24065
  result: exports_external.string(),
24066
+ appVersion: exports_external.string().optional(),
24066
24067
  usage: IterationUsageSchema.partial().optional()
24067
24068
  });
24068
24069
  var StateSchema = exports_external.object({
@@ -18928,8 +18928,8 @@ import { readFileSync } from "fs";
18928
18928
  import { resolve } from "path";
18929
18929
  function getVersion() {
18930
18930
  try {
18931
- if ("3.10.1")
18932
- return "3.10.1";
18931
+ if ("3.10.3")
18932
+ return "3.10.3";
18933
18933
  } catch {}
18934
18934
  const dirsToTry = [];
18935
18935
  try {
@@ -84163,7 +84163,7 @@ function projectLayout(root) {
84163
84163
  stateFile: (name) => join6(statesDir, name, STATE_FILE)
84164
84164
  };
84165
84165
  }
84166
- var STATE_FILE = ".ralph-state.json";
84166
+ var STATE_FILE = ".ralph-state.json", GAVEUP_COUNT_FILE = ".ralph-gaveup-count";
84167
84167
  var init_layout = __esm(() => {
84168
84168
  init_context();
84169
84169
  });
@@ -88862,6 +88862,7 @@ var init_types2 = __esm(() => {
88862
88862
  engine: exports_external2.string(),
88863
88863
  model: exports_external2.string(),
88864
88864
  result: exports_external2.string(),
88865
+ appVersion: exports_external2.string().optional(),
88865
88866
  usage: IterationUsageSchema.partial().optional()
88866
88867
  });
88867
88868
  StateSchema = exports_external2.object({
@@ -99056,12 +99057,20 @@ var init_loop_machine = __esm(() => {
99056
99057
  });
99057
99058
  });
99058
99059
 
99060
+ // packages/core/src/machines/mcp-registry.ts
99061
+ var init_mcp_registry = __esm(() => {
99062
+ init_example_machine();
99063
+ init_flow_machine();
99064
+ init_loop_machine();
99065
+ });
99066
+
99059
99067
  // packages/core/src/machines/index.ts
99060
99068
  var init_machines = __esm(() => {
99061
99069
  init_example_machine();
99062
99070
  init_flow_machine();
99063
99071
  init_flow_actor_store();
99064
99072
  init_loop_machine();
99073
+ init_mcp_registry();
99065
99074
  });
99066
99075
 
99067
99076
  // packages/core/src/tasks-md.ts
@@ -99629,6 +99638,7 @@ function updateStateIteration(stateDir, result2, startedAt, engine, model, usage
99629
99638
  engine,
99630
99639
  model,
99631
99640
  result: result2,
99641
+ appVersion: VERSION,
99632
99642
  usage: usage ? {
99633
99643
  cost_usd: usage.cost_usd,
99634
99644
  duration_ms: usage.duration_ms,
@@ -99690,6 +99700,7 @@ function mergeUsage(base2, resumed) {
99690
99700
  }
99691
99701
  var STEERING_MAX_LINES = 20;
99692
99702
  var init_loop = __esm(() => {
99703
+ init_version();
99693
99704
  init_state();
99694
99705
  init_context();
99695
99706
  init_tasks_md();
@@ -100427,7 +100438,7 @@ import { join as join16, dirname as dirname7 } from "path";
100427
100438
  import { homedir as homedir4 } from "os";
100428
100439
  import { mkdir as mkdir5 } from "fs/promises";
100429
100440
  function fmt(type, text) {
100430
- return `[${new Date().toISOString()}] [${type}] ${text}
100441
+ return `[${new Date().toISOString()}] [v${VERSION}] [${type}] ${text}
100431
100442
  `;
100432
100443
  }
100433
100444
  function write(path, line) {
@@ -100469,6 +100480,7 @@ async function initWorkerLog(logFile) {
100469
100480
  }
100470
100481
  var jsonLogChains, ANSI_RE, AGENT_LOG_PATH;
100471
100482
  var init_log = __esm(() => {
100483
+ init_version();
100472
100484
  jsonLogChains = new Map;
100473
100485
  ANSI_RE = /\x1b(?:\[[0-9;]*[A-Za-z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|.)/g;
100474
100486
  AGENT_LOG_PATH = join16(homedir4(), ".ralph", "agent-mode.log");
@@ -101730,7 +101742,7 @@ function findBoundaryViolations(changedFiles, patterns) {
101730
101742
  // apps/agent/src/shared/utils/ralph-comment.ts
101731
101743
  function isRalphComment(body) {
101732
101744
  const trimmed = body.trimStart();
101733
- return /^(\uD83E\uDD16|\uD83D\uDD04|\u2705|\u2717|\u26A0|\uD83D\uDD01|\uD83D\uDCCB)\s*Ralphy?\b/.test(trimmed);
101745
+ return /^(\uD83E\uDD16|\uD83D\uDD04|\u2705|\u2717|\u274C|\u26A0|\uD83D\uDD01|\uD83D\uDCCB|\u23F0)\s*Ralphy?\b/.test(trimmed);
101734
101746
  }
101735
101747
 
101736
101748
  // apps/agent/src/shared/capabilities/linear-client.ts
@@ -103303,7 +103315,7 @@ function emitFeatureSkipped(bus, id, reason) {
103303
103315
  var init_run_feature = () => {};
103304
103316
 
103305
103317
  // apps/agent/src/agent/post-task.ts
103306
- import { join as join21 } from "path";
103318
+ import { join as join21, dirname as dirname9 } from "path";
103307
103319
  function summarizeUncommittedStatus(stdout) {
103308
103320
  const lines = stdout.split(`
103309
103321
  `).filter((line) => line.length > 0);
@@ -103945,6 +103957,17 @@ async function runValidateOnlyPhase(input, deps) {
103945
103957
  await reactivateState(stateFilePath, log3, changeName);
103946
103958
  return respawnWorker();
103947
103959
  }
103960
+ async function recordGaveUp(stateFilePath, log3, changeName) {
103961
+ const path = join21(dirname9(stateFilePath), GAVEUP_COUNT_FILE);
103962
+ try {
103963
+ const file2 = Bun.file(path);
103964
+ const current = await file2.exists() ? Number.parseInt(await file2.text(), 10) || 0 : 0;
103965
+ await Bun.write(path, String(current + 1) + `
103966
+ `);
103967
+ } catch (err) {
103968
+ log3(`! could not record gave-up for ${changeName}: ${err.message}`, "yellow");
103969
+ }
103970
+ }
103948
103971
  async function runPostTask(input, deps) {
103949
103972
  const { log: log3, cmd, git: git2, runScript } = deps;
103950
103973
  const emit3 = (phase, detail) => deps.onPhase?.(phase, detail);
@@ -103988,6 +104011,8 @@ async function runPostTask(input, deps) {
103988
104011
  respawnWorker
103989
104012
  });
103990
104013
  emit3(effectiveCode === 0 ? "done" : "gave-up", effectiveCode !== 0 ? `exit ${effectiveCode}` : undefined);
104014
+ if (effectiveCode !== 0)
104015
+ await recordGaveUp(stateFilePath, log3, changeName);
103991
104016
  await runWorktreeCleanupPhase({ changeName, cwd: cwd2, projectRoot, useWorktree, effectiveCode, cfg }, { git: git2, log: log3, emit: emit3 });
103992
104017
  await runTeardownPhase({ cwd: cwd2, teardownScript: cfg.teardownScript }, { runScript, log: log3, emit: emit3 });
103993
104018
  return effectiveCode;
@@ -104062,6 +104087,8 @@ async function runPostTask(input, deps) {
104062
104087
  }
104063
104088
  const succeeded = effectiveCode === 0 || effectiveCode === NO_CHANGES_EXIT;
104064
104089
  emit3(succeeded ? "done" : "gave-up", succeeded ? undefined : `exit ${effectiveCode}`);
104090
+ if (!succeeded)
104091
+ await recordGaveUp(stateFilePath, log3, changeName);
104065
104092
  await runWorktreeCleanupPhase({ changeName, cwd: cwd2, projectRoot, useWorktree, effectiveCode, cfg }, { git: git2, log: log3, emit: emit3 });
104066
104093
  await runTeardownPhase({ cwd: cwd2, teardownScript: cfg.teardownScript }, { runScript, log: log3, emit: emit3 });
104067
104094
  return effectiveCode;
@@ -104079,6 +104106,7 @@ var CI_FAILED_EXIT = 70, PR_FAILED_EXIT = 71, NO_CHANGES_EXIT = 72, repoAutoMerg
104079
104106
  return { exitCode: proc.exitCode ?? 1, output };
104080
104107
  };
104081
104108
  var init_post_task = __esm(() => {
104109
+ init_layout();
104082
104110
  init_tasks_md();
104083
104111
  init_fs_change();
104084
104112
  init_git2();
@@ -105187,7 +105215,7 @@ var init_detections = __esm(() => {
105187
105215
  });
105188
105216
 
105189
105217
  // apps/agent/src/features/confirmation/state.ts
105190
- import { dirname as dirname9, join as join23 } from "path";
105218
+ import { dirname as dirname10, join as join23 } from "path";
105191
105219
  import { mkdir as mkdir8 } from "fs/promises";
105192
105220
  async function readConfirmationState(statePath) {
105193
105221
  const f2 = Bun.file(statePath);
@@ -105212,7 +105240,7 @@ async function readConfirmationState(statePath) {
105212
105240
  return { stateObj, confirmation };
105213
105241
  }
105214
105242
  async function writeConfirmationState(statePath, stateObj, confirmation) {
105215
- await mkdir8(dirname9(statePath), { recursive: true });
105243
+ await mkdir8(dirname10(statePath), { recursive: true });
105216
105244
  await Bun.write(statePath, JSON.stringify({ ...stateObj, confirmation }, null, 2) + `
105217
105245
  `);
105218
105246
  }
@@ -105454,7 +105482,7 @@ var init_inspect = __esm(() => {
105454
105482
  });
105455
105483
 
105456
105484
  // apps/agent/src/features/confirmation/awaiting.ts
105457
- import { join as join24, dirname as dirname10 } from "path";
105485
+ import { join as join24, dirname as dirname11 } from "path";
105458
105486
  import { mkdir as mkdir9 } from "fs/promises";
105459
105487
  async function resolveChangeCwdForIssue(issue2, changeName, deps) {
105460
105488
  const tracked = deps.cwdOf(changeName);
@@ -105516,7 +105544,7 @@ async function postPlanReadyCommentOnce(issue2, statePath, changeName, deps) {
105516
105544
  rounds: confirmation?.rounds ?? 0
105517
105545
  };
105518
105546
  try {
105519
- await mkdir9(dirname10(statePath), { recursive: true });
105547
+ await mkdir9(dirname11(statePath), { recursive: true });
105520
105548
  await Bun.write(statePath, JSON.stringify({ ...stateObj, confirmation: nextConfirmation }, null, 2) + `
105521
105549
  `);
105522
105550
  } catch (err) {
@@ -105560,6 +105588,10 @@ async function releaseAwaitingMarker(issue2, statePath, deps) {
105560
105588
  deps.onLog(`! persist cleared awaitingMarkerAppliedAt for ${issue2.identifier}: ${err.message}`, "yellow");
105561
105589
  }
105562
105590
  }
105591
+ function confirmationUsesCommentIndicator(cfg) {
105592
+ const { getApproved, getAutoApprove, getConfirmGate } = cfg.linear.indicators;
105593
+ return [getApproved, getAutoApprove, getConfirmGate].some((g) => g?.filter.some((m) => m.type === "comment"));
105594
+ }
105563
105595
  async function processAwaitingForIssue(issue2, deps) {
105564
105596
  try {
105565
105597
  const { cfg, apiKey, indicators } = deps;
@@ -105580,10 +105612,26 @@ async function processAwaitingForIssue(issue2, deps) {
105580
105612
  const tasks2 = await readTextOrNull(join24(changeDir, "tasks.md"));
105581
105613
  const proposal = await readTextOrNull(join24(changeDir, "proposal.md"));
105582
105614
  const design = await readTextOrNull(join24(changeDir, "design.md"));
105615
+ let commentsCache = null;
105616
+ const getComments = async () => {
105617
+ if (commentsCache)
105618
+ return commentsCache;
105619
+ if (!apiKey)
105620
+ return commentsCache = [];
105621
+ try {
105622
+ const cs = await fetchIssueComments(apiKey, issue2.id);
105623
+ commentsCache = cs.map((c) => ({ id: c.id, body: c.body, createdAt: c.createdAt }));
105624
+ } catch {
105625
+ commentsCache = [];
105626
+ }
105627
+ return commentsCache;
105628
+ };
105629
+ const commentBodies = confirmationUsesCommentIndicator(cfg) ? (await getComments()).filter((c) => !isRalphComment(c.body)).map((c) => c.body) : undefined;
105583
105630
  const ticketView = {
105584
105631
  labels: issue2.labels,
105585
105632
  state: issue2.state,
105586
- project: issue2.project
105633
+ project: issue2.project,
105634
+ ...commentBodies ? { commentBodies } : {}
105587
105635
  };
105588
105636
  const { approved: approvalMatches, confirmationGated } = computeConfirmationFlags(cfg, ticketView);
105589
105637
  const { stateObj, confirmation } = await readConfirmationState(statePath);
@@ -105655,16 +105703,7 @@ async function processAwaitingForIssue(issue2, deps) {
105655
105703
  postComments: cfg.linear.postComments !== false && Boolean(apiKey)
105656
105704
  }, {
105657
105705
  approvalMatches,
105658
- fetchComments: async () => {
105659
- if (!apiKey)
105660
- return [];
105661
- try {
105662
- const cs = await fetchIssueComments(apiKey, issue2.id);
105663
- return cs.map((c) => ({ id: c.id, body: c.body, createdAt: c.createdAt }));
105664
- } catch {
105665
- return [];
105666
- }
105667
- },
105706
+ fetchComments: getComments,
105668
105707
  ...indicators.clearApproved ? { clearApproved: indicators.clearApproved } : {},
105669
105708
  applyIndicator: (ind) => deps.applyIndicator(issue2, ind),
105670
105709
  postComment: async (body) => {
@@ -106523,17 +106562,17 @@ var init_pr_discovery = __esm(() => {
106523
106562
  });
106524
106563
 
106525
106564
  // apps/agent/src/features/review-followup/scan.ts
106526
- import { dirname as dirname11, join as join26 } from "path";
106565
+ import { dirname as dirname12, join as join26 } from "path";
106527
106566
  async function resolveReviewStateDir(changeName, deps) {
106528
106567
  const root = deps.cwdOf(changeName);
106529
106568
  if (root)
106530
- return dirname11(projectLayout(root).stateFile(changeName));
106569
+ return dirname12(projectLayout(root).stateFile(changeName));
106531
106570
  if (!deps.useWorktree)
106532
- return dirname11(projectLayout(deps.projectRoot).stateFile(changeName));
106571
+ return dirname12(projectLayout(deps.projectRoot).stateFile(changeName));
106533
106572
  const wtPath = join26(worktreesDir2(deps.projectRoot), changeName);
106534
106573
  const statePath = projectLayout(wtPath).stateFile(changeName);
106535
106574
  if (await Bun.file(statePath).exists())
106536
- return dirname11(statePath);
106575
+ return dirname12(statePath);
106537
106576
  return null;
106538
106577
  }
106539
106578
  async function readReviewWatermark(stateDir) {
@@ -107571,7 +107610,7 @@ var init_linear_sync = __esm(() => {
107571
107610
  });
107572
107611
 
107573
107612
  // apps/agent/src/agent/linear-sync/comment-sync.ts
107574
- import { dirname as dirname12, join as join30 } from "path";
107613
+ import { dirname as dirname13, join as join30 } from "path";
107575
107614
  import { mkdir as mkdir11, rename, unlink as unlink2 } from "fs/promises";
107576
107615
  async function readStateJson(statePath) {
107577
107616
  const file2 = Bun.file(statePath);
@@ -107584,7 +107623,7 @@ async function readStateJson(statePath) {
107584
107623
  }
107585
107624
  }
107586
107625
  async function writeStateJson(statePath, state) {
107587
- await mkdir11(dirname12(statePath), { recursive: true });
107626
+ await mkdir11(dirname13(statePath), { recursive: true });
107588
107627
  const tmp = `${statePath}.tmp-${process.pid}-${writeStateSeq++}`;
107589
107628
  try {
107590
107629
  await Bun.write(tmp, JSON.stringify(state, null, 2) + `
@@ -260014,7 +260053,7 @@ var init_render_pdf = __esm(() => {
260014
260053
  });
260015
260054
 
260016
260055
  // apps/agent/src/agent/linear-sync/spec-attachments.ts
260017
- import { dirname as dirname13, join as join31 } from "path";
260056
+ import { dirname as dirname14, join as join31 } from "path";
260018
260057
  function describeLinearError(err) {
260019
260058
  const e = err;
260020
260059
  const parts = [e.message ?? String(err)];
@@ -260029,7 +260068,7 @@ function describeLinearError(err) {
260029
260068
  return parts.join(" ");
260030
260069
  }
260031
260070
  function stateDirOf(statePath) {
260032
- return dirname13(statePath);
260071
+ return dirname14(statePath);
260033
260072
  }
260034
260073
  async function readRawState(statePath) {
260035
260074
  const file2 = Bun.file(statePath);
@@ -260739,7 +260778,19 @@ function buildAgentCoordinator(input) {
260739
260778
  pollInterval,
260740
260779
  getWorkerCwd: (changeName) => cwdByChange.get(changeName),
260741
260780
  syncTasksEnabled: commentSync.enabled,
260742
- runBaselineGate: runBaselineGateOnce
260781
+ runBaselineGate: runBaselineGateOnce,
260782
+ getGaveUpTotal: async () => {
260783
+ let total = 0;
260784
+ for (const [changeName, root] of cwdByChange) {
260785
+ const file2 = Bun.file(join33(projectLayout(root).taskStateDir(changeName), GAVEUP_COUNT_FILE));
260786
+ if (!await file2.exists())
260787
+ continue;
260788
+ try {
260789
+ total += Number.parseInt(await file2.text(), 10) || 0;
260790
+ } catch {}
260791
+ }
260792
+ return total;
260793
+ }
260743
260794
  };
260744
260795
  }
260745
260796
  var init_wire = __esm(() => {
@@ -260765,19 +260816,19 @@ var init_wire = __esm(() => {
260765
260816
 
260766
260817
  // apps/agent/src/agent/json-log/json-log-file.ts
260767
260818
  import { mkdir as mkdir12, appendFile as appendFile2 } from "fs/promises";
260768
- import { dirname as dirname14 } from "path";
260819
+ import { dirname as dirname15 } from "path";
260769
260820
  function createJsonLogFileSink(path) {
260770
260821
  if (!path)
260771
260822
  return { emit: () => {} };
260772
260823
  let chain2 = (async () => {
260773
260824
  try {
260774
- await mkdir12(dirname14(path), { recursive: true });
260825
+ await mkdir12(dirname15(path), { recursive: true });
260775
260826
  await Bun.write(path, "");
260776
260827
  } catch {}
260777
260828
  })();
260778
260829
  return {
260779
260830
  emit(event) {
260780
- const line = JSON.stringify({ ts: Date.now(), ...event }) + `
260831
+ const line = JSON.stringify({ ts: Date.now(), v: VERSION, ...event }) + `
260781
260832
  `;
260782
260833
  chain2 = chain2.then(async () => {
260783
260834
  try {
@@ -260787,7 +260838,9 @@ function createJsonLogFileSink(path) {
260787
260838
  }
260788
260839
  };
260789
260840
  }
260790
- var init_json_log_file = () => {};
260841
+ var init_json_log_file = __esm(() => {
260842
+ init_version();
260843
+ });
260791
260844
 
260792
260845
  // apps/agent/src/runtime/shutdown.ts
260793
260846
  async function waitForActiveWorkers(deps) {
@@ -261365,6 +261418,7 @@ function AgentMode({
261365
261418
  const [focusedIdx, setFocusedIdx] = import_react62.useState(0);
261366
261419
  const [showPendingTasks, setShowPendingTasks] = import_react62.useState(false);
261367
261420
  const [showAllSubtasks, setShowAllSubtasks] = import_react62.useState(false);
261421
+ const [gaveUpCount, setGaveUpCount] = import_react62.useState(0);
261368
261422
  const coordRef = import_react62.useRef(null);
261369
261423
  const workerMetaRef = import_react62.useRef(new Map);
261370
261424
  const gatedTicketsRef = import_react62.useRef(new Map);
@@ -261415,7 +261469,7 @@ function AgentMode({
261415
261469
  }, 100);
261416
261470
  return;
261417
261471
  }
261418
- const { coord: coord2, filterDesc, concurrency, pollInterval, runBaselineGate: runBaselineGate2 } = buildCoordinator({
261472
+ const { coord: coord2, filterDesc, concurrency, pollInterval, runBaselineGate: runBaselineGate2, getGaveUpTotal } = buildCoordinator({
261419
261473
  args,
261420
261474
  cfg: cfg2,
261421
261475
  projectRoot,
@@ -261561,6 +261615,12 @@ function AgentMode({
261561
261615
  if (cancelled)
261562
261616
  return;
261563
261617
  fileEmit({ type: "poll_done", found, added, buckets, prStatus });
261618
+ getGaveUpTotal().then((total) => {
261619
+ if (!cancelled)
261620
+ setGaveUpCount(total);
261621
+ }).catch(() => {
261622
+ return;
261623
+ });
261564
261624
  if (added > 0) {
261565
261625
  appendLog(` ${added} new issue${added === 1 ? "" : "s"} queued (found ${found} open)`);
261566
261626
  }
@@ -261872,7 +261932,14 @@ function AgentMode({
261872
261932
  cfg.useWorktree && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
261873
261933
  color: "green",
261874
261934
  children: " \u25CF worktree"
261875
- }, undefined, false, undefined, this)
261935
+ }, undefined, false, undefined, this),
261936
+ gaveUpCount > 0 && /* @__PURE__ */ jsx_dev_runtime11.jsxDEV(Text, {
261937
+ color: "red",
261938
+ children: [
261939
+ " \u2502 gave-up \xD7",
261940
+ gaveUpCount
261941
+ ]
261942
+ }, undefined, true, undefined, this)
261876
261943
  ]
261877
261944
  }, undefined, true, undefined, this)
261878
261945
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neriros/ralphy",
3
- "version": "3.10.1",
3
+ "version": "3.10.3",
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",
@@ -56,6 +56,8 @@
56
56
  "check:duplicates": "bun scripts/check-duplicate-declarations.ts --diff",
57
57
  "check:duplicates:all": "bun scripts/check-duplicate-declarations.ts --all",
58
58
  "build:architecture": "bun run apps/agent/src/scripts/generate-architecture.ts",
59
+ "build:state-diagrams": "bun scripts/export-state-diagrams.ts",
60
+ "check:state-diagrams:ci": "bun scripts/export-state-diagrams.ts --check",
59
61
  "prepare": "bunx husky",
60
62
  "build:publish": "bunx nx run-many --target=build --projects=shell,mcp --output-style stream && bun run copy-assets",
61
63
  "copy-assets": "bun scripts/copy-assets.ts",