@neriros/ralphy 2.13.8 → 2.13.10

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/index.js CHANGED
@@ -48157,10 +48157,10 @@ var require_axios = __commonJS((exports, module) => {
48157
48157
  this.__CANCEL__ = true;
48158
48158
  }
48159
48159
  }
48160
- function settle(resolve, reject2, response) {
48160
+ function settle(resolve2, reject2, response) {
48161
48161
  const validateStatus = response.config.validateStatus;
48162
48162
  if (!response.status || !validateStatus || validateStatus(response.status)) {
48163
- resolve(response);
48163
+ resolve2(response);
48164
48164
  } else {
48165
48165
  reject2(new AxiosError("Request failed with status code " + response.status, response.status >= 400 && response.status < 500 ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE, response.config, response.request, response));
48166
48166
  }
@@ -49013,7 +49013,7 @@ var require_axios = __commonJS((exports, module) => {
49013
49013
  }
49014
49014
  var isHttpAdapterSupported = typeof process !== "undefined" && utils$1.kindOf(process) === "process";
49015
49015
  var wrapAsync = (asyncExecutor) => {
49016
- return new Promise((resolve, reject2) => {
49016
+ return new Promise((resolve2, reject2) => {
49017
49017
  let onDone;
49018
49018
  let isDone;
49019
49019
  const done = (value, isRejected) => {
@@ -49024,7 +49024,7 @@ var require_axios = __commonJS((exports, module) => {
49024
49024
  };
49025
49025
  const _resolve = (value) => {
49026
49026
  done(value);
49027
- resolve(value);
49027
+ resolve2(value);
49028
49028
  };
49029
49029
  const _reject = (reason) => {
49030
49030
  done(reason, true);
@@ -49085,7 +49085,7 @@ var require_axios = __commonJS((exports, module) => {
49085
49085
  }
49086
49086
  };
49087
49087
  var httpAdapter = isHttpAdapterSupported && function httpAdapter2(config) {
49088
- return wrapAsync(async function dispatchHttpRequest(resolve, reject2, onDone) {
49088
+ return wrapAsync(async function dispatchHttpRequest(resolve2, reject2, onDone) {
49089
49089
  const own2 = (key) => utils$1.hasOwnProp(config, key) ? config[key] : undefined;
49090
49090
  let data = own2("data");
49091
49091
  let lookup = own2("lookup");
@@ -49193,7 +49193,7 @@ var require_axios = __commonJS((exports, module) => {
49193
49193
  }
49194
49194
  let convertedData;
49195
49195
  if (method2 !== "GET") {
49196
- return settle(resolve, reject2, {
49196
+ return settle(resolve2, reject2, {
49197
49197
  status: 405,
49198
49198
  statusText: "method not allowed",
49199
49199
  headers: {},
@@ -49215,7 +49215,7 @@ var require_axios = __commonJS((exports, module) => {
49215
49215
  } else if (responseType === "stream") {
49216
49216
  convertedData = stream.Readable.from(convertedData);
49217
49217
  }
49218
- return settle(resolve, reject2, {
49218
+ return settle(resolve2, reject2, {
49219
49219
  data: convertedData,
49220
49220
  status: 200,
49221
49221
  statusText: "OK",
@@ -49442,7 +49442,7 @@ var require_axios = __commonJS((exports, module) => {
49442
49442
  });
49443
49443
  }
49444
49444
  response.data = responseStream;
49445
- settle(resolve, reject2, response);
49445
+ settle(resolve2, reject2, response);
49446
49446
  } else {
49447
49447
  const responseBuffer = [];
49448
49448
  let totalResponseBytes = 0;
@@ -49481,7 +49481,7 @@ var require_axios = __commonJS((exports, module) => {
49481
49481
  } catch (err) {
49482
49482
  return reject2(AxiosError.from(err, null, config, response.request, response));
49483
49483
  }
49484
- settle(resolve, reject2, response);
49484
+ settle(resolve2, reject2, response);
49485
49485
  });
49486
49486
  }
49487
49487
  abortEmitter.once("abort", (err) => {
@@ -49782,7 +49782,7 @@ var require_axios = __commonJS((exports, module) => {
49782
49782
  };
49783
49783
  var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
49784
49784
  var xhrAdapter = isXHRAdapterSupported && function(config) {
49785
- return new Promise(function dispatchXhrRequest(resolve, reject2) {
49785
+ return new Promise(function dispatchXhrRequest(resolve2, reject2) {
49786
49786
  const _config = resolveConfig(config);
49787
49787
  let requestData = _config.data;
49788
49788
  const requestHeaders = AxiosHeaders.from(_config.headers).normalize();
@@ -49818,7 +49818,7 @@ var require_axios = __commonJS((exports, module) => {
49818
49818
  request
49819
49819
  };
49820
49820
  settle(function _resolve(value) {
49821
- resolve(value);
49821
+ resolve2(value);
49822
49822
  done();
49823
49823
  }, function _reject(err) {
49824
49824
  reject2(err);
@@ -50247,8 +50247,8 @@ var require_axios = __commonJS((exports, module) => {
50247
50247
  }
50248
50248
  }
50249
50249
  !isStreamResponse && unsubscribe && unsubscribe();
50250
- return await new Promise((resolve, reject2) => {
50251
- settle(resolve, reject2, {
50250
+ return await new Promise((resolve2, reject2) => {
50251
+ settle(resolve2, reject2, {
50252
50252
  data: responseData,
50253
50253
  headers: AxiosHeaders.from(response.headers),
50254
50254
  status: response.status,
@@ -50640,8 +50640,8 @@ var require_axios = __commonJS((exports, module) => {
50640
50640
  throw new TypeError("executor must be a function.");
50641
50641
  }
50642
50642
  let resolvePromise;
50643
- this.promise = new Promise(function promiseExecutor(resolve) {
50644
- resolvePromise = resolve;
50643
+ this.promise = new Promise(function promiseExecutor(resolve2) {
50644
+ resolvePromise = resolve2;
50645
50645
  });
50646
50646
  const token = this;
50647
50647
  this.promise.then((cancel) => {
@@ -50655,9 +50655,9 @@ var require_axios = __commonJS((exports, module) => {
50655
50655
  });
50656
50656
  this.promise.then = (onfulfilled) => {
50657
50657
  let _resolve;
50658
- const promise = new Promise((resolve) => {
50659
- token.subscribe(resolve);
50660
- _resolve = resolve;
50658
+ const promise = new Promise((resolve2) => {
50659
+ token.subscribe(resolve2);
50660
+ _resolve = resolve2;
50661
50661
  }).then(onfulfilled);
50662
50662
  promise.cancel = function reject2() {
50663
50663
  token.unsubscribe(_resolve);
@@ -50837,7 +50837,7 @@ var require_axios = __commonJS((exports, module) => {
50837
50837
  });
50838
50838
 
50839
50839
  // apps/cli/src/index.ts
50840
- import { resolve, join as join19, dirname as dirname5 } from "path";
50840
+ import { resolve as resolve2, join as join19, dirname as dirname5 } from "path";
50841
50841
  import { exists as exists2, mkdir as mkdir5, rm } from "fs/promises";
50842
50842
 
50843
50843
  // node_modules/.bun/ink@5.2.1+1f88f629f0141b18/node_modules/ink/build/render.js
@@ -56406,102 +56406,36 @@ function styled(text, style) {
56406
56406
  function log(msg) {
56407
56407
  console.log(typeof msg === "string" ? msg : format(msg));
56408
56408
  }
56409
- // package.json
56410
- var package_default = {
56411
- name: "@neriros/ralphy",
56412
- version: "2.13.8",
56413
- description: "An iterative AI task execution framework. Orchestrates multi-phase autonomous work using Claude or Codex engines.",
56414
- keywords: [
56415
- "agent",
56416
- "ai",
56417
- "claude",
56418
- "cli",
56419
- "loop",
56420
- "mcp",
56421
- "ralph",
56422
- "task-runner"
56423
- ],
56424
- license: "MIT",
56425
- repository: {
56426
- type: "git",
56427
- url: "https://github.com/NeriRos/ralphy.git"
56428
- },
56429
- bin: {
56430
- ralphy: "./dist/cli/index.js",
56431
- "ralphy-mcp": "./dist/mcp/index.js"
56432
- },
56433
- workspaces: [
56434
- "packages/*",
56435
- "apps/*",
56436
- "tools/generators/*"
56437
- ],
56438
- files: [
56439
- "dist/cli/index.js",
56440
- "dist/mcp/index.js",
56441
- "README.md"
56442
- ],
56443
- type: "module",
56444
- scripts: {
56445
- ralph: "bun .ralph/bin/cli.js",
56446
- lint: "oxlint --config .oxlintrc.json .",
56447
- "lint:fix": "oxlint --config .oxlintrc.json --fix .",
56448
- fmt: "oxfmt --write .",
56449
- "fmt:check": "oxfmt --check .",
56450
- typecheck: "nx affected -t typecheck",
56451
- "check:deps": "depcruise packages/*/src apps/*/src --config .dependency-cruiser.cjs",
56452
- "check:unused": "knip",
56453
- "lint:ci": "nx affected -t lint --exclude=ui",
56454
- "fmt:ci": "nx affected -t fmt:check --exclude=ui",
56455
- "typecheck:ci": "nx affected -t typecheck --parallel=1 --exclude=ui",
56456
- "test:ci": "nx affected -t test --exclude=ui",
56457
- "test:affected-files:coverage:ci": "bun scripts/bun-test-affected-files.ts --coverage",
56458
- "test:coverage:ci": "nx affected -t test:coverage --exclude=ui",
56459
- "build:ci": "nx affected -t build --exclude=ui",
56460
- "check:circular:ci": "depcruise packages/*/src apps/*/src --config .dependency-cruiser.cjs",
56461
- "check:unused:ci": "knip",
56462
- "check:outdated:ci": "bun scripts/check-outdated.ts",
56463
- prepare: "bunx husky",
56464
- "build:publish": "bunx nx run-many --target=build --projects=cli,mcp --output-style stream && bun run copy-assets",
56465
- "copy-assets": "bun scripts/copy-assets.ts",
56466
- prepublishOnly: "bun run build:publish"
56467
- },
56468
- devDependencies: {
56469
- "@commitlint/cli": "^20.4.3",
56470
- "@commitlint/config-conventional": "^20.4.3",
56471
- "@fission-ai/openspec": "latest",
56472
- "@modelcontextprotocol/sdk": "^1.12.0",
56473
- "@nx/devkit": "^22.7.1",
56474
- "@nx/js": "^22.7.1",
56475
- "@secretlint/secretlint-rule-preset-recommend": "^11.3.1",
56476
- "@swc-node/register": "^1.11.1",
56477
- "@swc/core": "^1.15.18",
56478
- "@total-typescript/ts-reset": "^0.6.1",
56479
- "@types/node": "^22.0.0",
56480
- "bun-types": "^1.3.0",
56481
- chalk: "^5.4.0",
56482
- "dependency-cruiser": "^17.3.8",
56483
- husky: "^9.1.7",
56484
- knip: "^5.85.0",
56485
- "lint-staged": "^16.3.2",
56486
- nx: "22.5.3",
56487
- "oxc-parser": "^0.126.0",
56488
- oxfmt: "^0.36.0",
56489
- oxlint: "^1.51.0",
56490
- secretlint: "^11.3.1",
56491
- typescript: "^5.8.0",
56492
- zod: "^3.24.0"
56493
- },
56494
- overrides: {
56495
- axios: "^1.15.1",
56496
- minimatch: "^10.2.3"
56497
- },
56498
- engines: {
56499
- bun: ">=1.0.0"
56500
- }
56501
- };
56502
56409
 
56503
56410
  // apps/cli/src/cli.ts
56504
- var VERSION = package_default.version;
56411
+ import { readFileSync as readFileSync2 } from "fs";
56412
+ import { resolve } from "path";
56413
+ function getVersion() {
56414
+ const dirsToTry = [];
56415
+ try {
56416
+ const cliDir = import.meta.dir;
56417
+ dirsToTry.push(cliDir);
56418
+ } catch {}
56419
+ dirsToTry.push(process.cwd());
56420
+ for (const startDir of dirsToTry) {
56421
+ let current = startDir;
56422
+ for (let i = 0;i < 10; i++) {
56423
+ const pkgPath = resolve(current, "package.json");
56424
+ try {
56425
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
56426
+ if (pkg.workspaces && pkg.version && pkg.version !== "0.0.0") {
56427
+ return pkg.version;
56428
+ }
56429
+ } catch {}
56430
+ const parent = resolve(current, "..");
56431
+ if (parent === current)
56432
+ break;
56433
+ current = parent;
56434
+ }
56435
+ }
56436
+ return "unknown";
56437
+ }
56438
+ var VERSION = getVersion();
56505
56439
  var VALID_MODES = new Set(["task", "list", "status", "init", "agent", "clean"]);
56506
56440
  var VALID_MODELS = new Set(["haiku", "sonnet", "opus"]);
56507
56441
  var INDICATOR_KEYS = new Set([
@@ -56541,6 +56475,7 @@ var HELP_TEXT = [
56541
56475
  " --max-runtime <n> Stop after N minutes of wall-clock time (0 = no limit)",
56542
56476
  " --max-failures <n> Stop after N consecutive failures (default: 5, 0 = disable)",
56543
56477
  " --unlimited No iteration limit (default)",
56478
+ " --manual-test Enable manual testing phase (create test tasks in tasks.md)",
56544
56479
  " --log Log raw engine stream",
56545
56480
  " --verbose Verbose output",
56546
56481
  "",
@@ -56637,6 +56572,7 @@ async function parseArgs(argv) {
56637
56572
  delay: 0,
56638
56573
  log: false,
56639
56574
  verbose: false,
56575
+ manualTest: false,
56640
56576
  linearTeam: "",
56641
56577
  linearAssignee: "",
56642
56578
  pollInterval: 60,
@@ -56830,6 +56766,9 @@ async function parseArgs(argv) {
56830
56766
  case "--fix-ci":
56831
56767
  result2.fixCi = true;
56832
56768
  break;
56769
+ case "--manual-test":
56770
+ result2.manualTest = true;
56771
+ break;
56833
56772
  default:
56834
56773
  if (VALID_MODES.has(arg)) {
56835
56774
  result2.mode = arg;
@@ -56845,7 +56784,7 @@ async function parseArgs(argv) {
56845
56784
  // packages/context/src/context.ts
56846
56785
  import { AsyncLocalStorage } from "async_hooks";
56847
56786
  import {
56848
- readFileSync as readFileSync2,
56787
+ readFileSync as readFileSync3,
56849
56788
  writeFileSync,
56850
56789
  existsSync as existsSync2,
56851
56790
  unlinkSync,
@@ -56858,7 +56797,7 @@ class FileSystemProvider {
56858
56797
  read(path) {
56859
56798
  if (!existsSync2(path))
56860
56799
  return null;
56861
- return readFileSync2(path, "utf-8");
56800
+ return readFileSync3(path, "utf-8");
56862
56801
  }
56863
56802
  write(path, content) {
56864
56803
  mkdirSync(dirname(path), { recursive: true });
@@ -60918,6 +60857,7 @@ var StateSchema = exports_external.object({
60918
60857
  lastModified: exports_external.string(),
60919
60858
  engine: exports_external.enum(["claude", "codex"]).default("claude"),
60920
60859
  model: exports_external.string().default("opus"),
60860
+ manualTest: exports_external.boolean().default(false),
60921
60861
  usage: UsageSchema.default({}),
60922
60862
  history: exports_external.array(HistoryEntrySchema).default([]),
60923
60863
  metadata: exports_external.object({ branch: exports_external.string().optional() }).default({})
@@ -60992,6 +60932,7 @@ function buildInitialState(options) {
60992
60932
  prompt: options.prompt,
60993
60933
  engine: options.engine ?? "claude",
60994
60934
  model: options.model ?? "opus",
60935
+ manualTest: options.manualTest ?? false,
60995
60936
  createdAt: now2,
60996
60937
  lastModified: now2,
60997
60938
  metadata: { branch }
@@ -65749,10 +65690,10 @@ async function runEngine(opts) {
65749
65690
  rawWriter.write(line + `
65750
65691
  `);
65751
65692
  };
65752
- const closeRaw = () => new Promise((resolve) => {
65693
+ const closeRaw = () => new Promise((resolve2) => {
65753
65694
  if (!rawWriter)
65754
- return resolve();
65755
- rawWriter.end(resolve);
65695
+ return resolve2();
65696
+ rawWriter.end(resolve2);
65756
65697
  });
65757
65698
  const emit = opts.onFeedEvent;
65758
65699
  function emitEvent(event) {
@@ -66578,14 +66519,14 @@ async function addSourceContext(frames) {
66578
66519
  return frames;
66579
66520
  }
66580
66521
  function getContextLinesFromFile(path, ranges, output) {
66581
- return new Promise((resolve) => {
66522
+ return new Promise((resolve2) => {
66582
66523
  const stream = createReadStream(path);
66583
66524
  const lineReaded = createInterface({
66584
66525
  input: stream
66585
66526
  });
66586
66527
  function destroyStreamAndResolve() {
66587
66528
  stream.destroy();
66588
- resolve();
66529
+ resolve2();
66589
66530
  }
66590
66531
  let lineNumber = 0;
66591
66532
  let currentRangeIndex = 0;
@@ -69117,15 +69058,15 @@ class PostHogBackendClient extends PostHogCoreStateless {
69117
69058
  if (this.featureFlagsPoller === undefined) {
69118
69059
  return false;
69119
69060
  }
69120
- return new Promise((resolve) => {
69061
+ return new Promise((resolve2) => {
69121
69062
  const timeout = setTimeout(() => {
69122
69063
  cleanup();
69123
- resolve(false);
69064
+ resolve2(false);
69124
69065
  }, timeoutMs);
69125
69066
  const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
69126
69067
  clearTimeout(timeout);
69127
69068
  cleanup();
69128
- resolve(count > 0);
69069
+ resolve2(count > 0);
69129
69070
  });
69130
69071
  });
69131
69072
  }
@@ -69612,6 +69553,34 @@ function buildTaskPrompt(state, taskDir) {
69612
69553
 
69613
69554
  `;
69614
69555
  }
69556
+ if (state.manualTest) {
69557
+ const tasksContent2 = storage.read(join7(taskDir, "tasks.md"));
69558
+ const hasUncheckedTasks = tasksContent2 !== null && /^- \[ \]/m.test(tasksContent2);
69559
+ if (!hasUncheckedTasks) {
69560
+ const hasManualTestSection = tasksContent2 !== null && /^## Manual Testing/m.test(tasksContent2);
69561
+ if (!hasManualTestSection) {
69562
+ prompt += `---
69563
+
69564
+ ## Manual Testing Phase
69565
+
69566
+ `;
69567
+ prompt += `All primary implementation tasks are complete. Now create manual test tasks.
69568
+
69569
+ `;
69570
+ prompt += `1. Analyze the specification and implementation
69571
+ `;
69572
+ prompt += `2. Identify critical manual test scenarios (UI interactions, edge cases, user workflows, integration testing)
69573
+ `;
69574
+ prompt += "3. Add a `## Manual Testing` section to tasks.md with test items as `- [ ] Test scenario description`\n";
69575
+ prompt += `4. Complete each test and check it off when done
69576
+
69577
+ `;
69578
+ prompt += `---
69579
+
69580
+ `;
69581
+ }
69582
+ }
69583
+ }
69615
69584
  prompt += `Change name: \`${state.name}\`
69616
69585
 
69617
69586
  `;
@@ -69729,7 +69698,7 @@ function mergeUsage(base2, resumed) {
69729
69698
  }
69730
69699
  // apps/cli/src/hooks/useLoop.ts
69731
69700
  function sleep(seconds) {
69732
- return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
69701
+ return new Promise((resolve2) => setTimeout(resolve2, seconds * 1000));
69733
69702
  }
69734
69703
  function useLoop(opts) {
69735
69704
  const [state, setState] = import_react55.useState(null);
@@ -69783,7 +69752,8 @@ function useLoop(opts) {
69783
69752
  name: opts.name,
69784
69753
  prompt: opts.prompt,
69785
69754
  engine: opts.engine,
69786
- model: opts.model
69755
+ model: opts.model,
69756
+ manualTest: opts.manualTest
69787
69757
  });
69788
69758
  writeState(stateDir, currentState);
69789
69759
  }
@@ -70188,6 +70158,7 @@ var RalphyConfigSchema = exports_external.object({
70188
70158
  iterationDelaySeconds: exports_external.number().int().nonnegative().default(0),
70189
70159
  logRawStream: exports_external.boolean().default(false),
70190
70160
  taskVerbose: exports_external.boolean().default(false),
70161
+ enableManualTest: exports_external.boolean().default(false),
70191
70162
  useWorktree: exports_external.boolean().default(false),
70192
70163
  cleanupWorktreeOnSuccess: exports_external.boolean().default(false),
70193
70164
  setupScript: exports_external.string().optional(),
@@ -70212,6 +70183,7 @@ var RalphyConfigSchema = exports_external.object({
70212
70183
  pollIntervalSeconds: 60,
70213
70184
  maxIterationsPerTask: 0,
70214
70185
  maxCostUsdPerTask: 0,
70186
+ enableManualTest: false,
70215
70187
  engine: "claude",
70216
70188
  model: "opus",
70217
70189
  linear: { postComments: true, updateEveryIterations: 10, indicators: {} }
@@ -70412,10 +70384,8 @@ function buildIssueFilter(spec) {
70412
70384
  branches.push({ state: { name: { in: statuses } } });
70413
70385
  if (labels.length > 0)
70414
70386
  branches.push({ labels: { some: { name: { in: labels } } } });
70415
- if (branches.length === 1)
70416
- Object.assign(where, branches[0]);
70417
- else
70418
- where.or = branches;
70387
+ for (const b of branches)
70388
+ Object.assign(where, b);
70419
70389
  } else {
70420
70390
  where.state = { type: { in: ["unstarted", "started", "backlog"] } };
70421
70391
  }
@@ -71862,6 +71832,8 @@ PR: ${prUrl}` : ""
71862
71832
  c.push("--log");
71863
71833
  if (args.verbose || cfg.taskVerbose)
71864
71834
  c.push("--verbose");
71835
+ if (args.manualTest || cfg.enableManualTest)
71836
+ c.push("--manual-test");
71865
71837
  return c;
71866
71838
  }
71867
71839
  function defaultSpawn(changeName, cmd, cwd2, note) {
@@ -73193,6 +73165,41 @@ function ErrorMessage({ message }) {
73193
73165
  children: message
73194
73166
  }, undefined, false, undefined, this);
73195
73167
  }
73168
+ function TaskModeWrapper({ args, statesDir, tasksDir, projectRoot }) {
73169
+ const [config, setConfig] = import_react58.useState(null);
73170
+ const [error, setError] = import_react58.useState(null);
73171
+ import_react58.useEffect(() => {
73172
+ loadRalphyConfig(projectRoot).then((cfg) => setConfig({ manualTest: cfg.enableManualTest })).catch((err) => setError(err.message));
73173
+ }, [projectRoot]);
73174
+ if (error) {
73175
+ return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ErrorMessage, {
73176
+ message: `Error loading config: ${error}`
73177
+ }, undefined, false, undefined, this);
73178
+ }
73179
+ if (!config) {
73180
+ return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {}, undefined, false, undefined, this);
73181
+ }
73182
+ const manualTest = args.manualTest || config.manualTest;
73183
+ return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(TaskLoop, {
73184
+ opts: {
73185
+ name: args.name,
73186
+ prompt: args.prompt,
73187
+ engine: args.engine,
73188
+ model: args.model,
73189
+ maxIterations: args.maxIterations,
73190
+ maxCostUsd: args.maxCostUsd,
73191
+ maxRuntimeMinutes: args.maxRuntimeMinutes,
73192
+ maxConsecutiveFailures: args.maxConsecutiveFailures,
73193
+ delay: args.delay,
73194
+ log: args.log,
73195
+ verbose: args.verbose,
73196
+ manualTest,
73197
+ statesDir,
73198
+ tasksDir,
73199
+ changeStore: new OpenSpecChangeStore
73200
+ }
73201
+ }, undefined, false, undefined, this);
73202
+ }
73196
73203
  function App2({ args, statesDir, tasksDir, projectRoot }) {
73197
73204
  switch (args.mode) {
73198
73205
  case "list":
@@ -73244,23 +73251,11 @@ function App2({ args, statesDir, tasksDir, projectRoot }) {
73244
73251
  message: "Error: --name is required for task mode"
73245
73252
  }, undefined, false, undefined, this);
73246
73253
  }
73247
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(TaskLoop, {
73248
- opts: {
73249
- name: args.name,
73250
- prompt: args.prompt,
73251
- engine: args.engine,
73252
- model: args.model,
73253
- maxIterations: args.maxIterations,
73254
- maxCostUsd: args.maxCostUsd,
73255
- maxRuntimeMinutes: args.maxRuntimeMinutes,
73256
- maxConsecutiveFailures: args.maxConsecutiveFailures,
73257
- delay: args.delay,
73258
- log: args.log,
73259
- verbose: args.verbose,
73260
- statesDir,
73261
- tasksDir,
73262
- changeStore: new OpenSpecChangeStore
73263
- }
73254
+ return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(TaskModeWrapper, {
73255
+ args,
73256
+ statesDir,
73257
+ tasksDir,
73258
+ projectRoot
73264
73259
  }, undefined, false, undefined, this);
73265
73260
  }
73266
73261
  }
@@ -73277,7 +73272,7 @@ async function findProjectRoot() {
73277
73272
  while (dir !== "/") {
73278
73273
  if (await exists2(join19(dir, "openspec")))
73279
73274
  return dir;
73280
- dir = resolve(dir, "..");
73275
+ dir = resolve2(dir, "..");
73281
73276
  }
73282
73277
  return process.cwd();
73283
73278
  }
package/dist/mcp/index.js CHANGED
@@ -23966,6 +23966,7 @@ var StateSchema = exports_external.object({
23966
23966
  lastModified: exports_external.string(),
23967
23967
  engine: exports_external.enum(["claude", "codex"]).default("claude"),
23968
23968
  model: exports_external.string().default("opus"),
23969
+ manualTest: exports_external.boolean().default(false),
23969
23970
  usage: UsageSchema.default({}),
23970
23971
  history: exports_external.array(HistoryEntrySchema).default([]),
23971
23972
  metadata: exports_external.object({ branch: exports_external.string().optional() }).default({})
@@ -24031,6 +24032,7 @@ function buildInitialState(options) {
24031
24032
  prompt: options.prompt,
24032
24033
  engine: options.engine ?? "claude",
24033
24034
  model: options.model ?? "opus",
24035
+ manualTest: options.manualTest ?? false,
24034
24036
  createdAt: now,
24035
24037
  lastModified: now,
24036
24038
  metadata: { branch }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neriros/ralphy",
3
- "version": "2.13.8",
3
+ "version": "2.13.10",
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",