poe-code 3.0.155 → 3.0.156

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/index.js CHANGED
@@ -925,16 +925,16 @@ function getConfigFormat(pathOrFormat) {
925
925
  }
926
926
  return formatRegistry[formatName];
927
927
  }
928
- function detectFormat(path43) {
929
- const ext = getExtension(path43);
928
+ function detectFormat(path48) {
929
+ const ext = getExtension(path48);
930
930
  return extensionMap[ext];
931
931
  }
932
- function getExtension(path43) {
933
- const lastDot = path43.lastIndexOf(".");
932
+ function getExtension(path48) {
933
+ const lastDot = path48.lastIndexOf(".");
934
934
  if (lastDot === -1) {
935
935
  return "";
936
936
  }
937
- return path43.slice(lastDot).toLowerCase();
937
+ return path48.slice(lastDot).toLowerCase();
938
938
  }
939
939
  var formatRegistry, extensionMap;
940
940
  var init_formats = __esm({
@@ -1265,8 +1265,8 @@ async function applyChmod(mutation, context, options) {
1265
1265
  };
1266
1266
  }
1267
1267
  try {
1268
- const stat13 = await context.fs.stat(targetPath);
1269
- const currentMode = typeof stat13.mode === "number" ? stat13.mode & 511 : null;
1268
+ const stat14 = await context.fs.stat(targetPath);
1269
+ const currentMode = typeof stat14.mode === "number" ? stat14.mode & 511 : null;
1270
1270
  if (currentMode === mutation.mode) {
1271
1271
  return {
1272
1272
  outcome: { changed: false, effect: "none", detail: "noop" },
@@ -1989,38 +1989,38 @@ import { createTwoFilesPatch } from "diff";
1989
1989
  import chalk from "chalk";
1990
1990
  function createDryRunFileSystem(base, recorder) {
1991
1991
  const proxy = {
1992
- async readFile(path43, encoding) {
1992
+ async readFile(path48, encoding) {
1993
1993
  if (encoding) {
1994
- return base.readFile(path43, encoding);
1994
+ return base.readFile(path48, encoding);
1995
1995
  }
1996
- return base.readFile(path43);
1996
+ return base.readFile(path48);
1997
1997
  },
1998
- async writeFile(path43, data, options) {
1999
- const previousContent = await tryReadText(base, path43);
1998
+ async writeFile(path48, data, options) {
1999
+ const previousContent = await tryReadText(base, path48);
2000
2000
  const nextContent = formatData(data, options?.encoding);
2001
2001
  recorder.record({
2002
2002
  type: "writeFile",
2003
- path: path43,
2003
+ path: path48,
2004
2004
  nextContent,
2005
2005
  previousContent
2006
2006
  });
2007
2007
  },
2008
- async mkdir(path43, options) {
2009
- recorder.record({ type: "mkdir", path: path43, options });
2008
+ async mkdir(path48, options) {
2009
+ recorder.record({ type: "mkdir", path: path48, options });
2010
2010
  },
2011
- async stat(path43) {
2012
- return base.stat(path43);
2011
+ async stat(path48) {
2012
+ return base.stat(path48);
2013
2013
  },
2014
- async unlink(path43) {
2015
- recorder.record({ type: "unlink", path: path43 });
2014
+ async unlink(path48) {
2015
+ recorder.record({ type: "unlink", path: path48 });
2016
2016
  },
2017
- async readdir(path43) {
2018
- return base.readdir(path43);
2017
+ async readdir(path48) {
2018
+ return base.readdir(path48);
2019
2019
  }
2020
2020
  };
2021
2021
  if (typeof base.rm === "function") {
2022
- proxy.rm = async (path43, options) => {
2023
- recorder.record({ type: "rm", path: path43, options });
2022
+ proxy.rm = async (path48, options) => {
2023
+ recorder.record({ type: "rm", path: path48, options });
2024
2024
  };
2025
2025
  }
2026
2026
  if (typeof base.copyFile === "function") {
@@ -2110,8 +2110,8 @@ function describeWriteChange(previous, next) {
2110
2110
  }
2111
2111
  return "update";
2112
2112
  }
2113
- function renderWriteCommand(path43, change) {
2114
- const command = `cat > ${path43}`;
2113
+ function renderWriteCommand(path48, change) {
2114
+ const command = `cat > ${path48}`;
2115
2115
  if (change === "create") {
2116
2116
  return renderOperationCommand(command, chalk.green, "# create");
2117
2117
  }
@@ -2273,9 +2273,9 @@ function redactTomlLine(line) {
2273
2273
  }
2274
2274
  return line;
2275
2275
  }
2276
- async function tryReadText(base, path43) {
2276
+ async function tryReadText(base, path48) {
2277
2277
  try {
2278
- return await base.readFile(path43, "utf8");
2278
+ return await base.readFile(path48, "utf8");
2279
2279
  } catch (error2) {
2280
2280
  if (isNotFound(error2)) {
2281
2281
  return null;
@@ -3404,6 +3404,9 @@ function resolveOutputFormat(env = process.env) {
3404
3404
  cached = VALID_FORMATS.has(raw) ? raw : "terminal";
3405
3405
  return cached;
3406
3406
  }
3407
+ function withOutputFormat(format, fn) {
3408
+ return formatStorage.run(format, fn);
3409
+ }
3407
3410
  function resetOutputFormatCache() {
3408
3411
  cached = void 0;
3409
3412
  }
@@ -7752,6 +7755,14 @@ async function text3(opts) {
7752
7755
  async function confirm2(opts) {
7753
7756
  return clack.confirm(opts);
7754
7757
  }
7758
+ async function confirmOrCancel(opts) {
7759
+ const result = await confirm2(opts);
7760
+ if (Ct(result)) {
7761
+ cancel("Operation cancelled.");
7762
+ throw new PromptCancelledError();
7763
+ }
7764
+ return result === true;
7765
+ }
7755
7766
  async function password2(opts) {
7756
7767
  return clack.password(opts);
7757
7768
  }
@@ -7818,6 +7829,7 @@ async function withSpinner(options) {
7818
7829
  throw error2;
7819
7830
  }
7820
7831
  }
7832
+ var PromptCancelledError;
7821
7833
  var init_prompts = __esm({
7822
7834
  "packages/design-system/src/prompts/index.ts"() {
7823
7835
  "use strict";
@@ -7829,6 +7841,15 @@ var init_prompts = __esm({
7829
7841
  init_note();
7830
7842
  init_outro();
7831
7843
  init_spinner2();
7844
+ PromptCancelledError = class extends Error {
7845
+ constructor(message2 = "Operation cancelled.") {
7846
+ super(message2);
7847
+ this.name = "PromptCancelledError";
7848
+ if (Error.captureStackTrace) {
7849
+ Error.captureStackTrace(this, this.constructor);
7850
+ }
7851
+ }
7852
+ };
7832
7853
  }
7833
7854
  });
7834
7855
 
@@ -8089,21 +8110,21 @@ async function* adaptClaude(lines) {
8089
8110
  if (blockType !== "tool_result") continue;
8090
8111
  const kind = toolKindsById.get(item.tool_use_id);
8091
8112
  toolKindsById.delete(item.tool_use_id);
8092
- let path43;
8113
+ let path48;
8093
8114
  if (typeof item.content === "string") {
8094
- path43 = item.content;
8115
+ path48 = item.content;
8095
8116
  } else {
8096
8117
  try {
8097
- path43 = JSON.stringify(item.content);
8118
+ path48 = JSON.stringify(item.content);
8098
8119
  } catch {
8099
- path43 = String(item.content);
8120
+ path48 = String(item.content);
8100
8121
  }
8101
8122
  }
8102
8123
  yield {
8103
8124
  event: "tool_complete",
8104
8125
  id: item.tool_use_id,
8105
8126
  kind,
8106
- path: path43
8127
+ path: path48
8107
8128
  };
8108
8129
  }
8109
8130
  }
@@ -8226,10 +8247,10 @@ async function* adaptCodex(lines) {
8226
8247
  const kindFromStart = toolKindById.get(item.id);
8227
8248
  const kind = kindFromStart ?? (itemType === "command_execution" ? "exec" : itemType === "file_edit" ? "edit" : "other");
8228
8249
  const titleFromEvent = isNonEmptyString(item.path) ? item.path : itemType === "mcp_tool_call" ? `${isNonEmptyString(item.server) ? item.server : "unknown"}.${isNonEmptyString(item.tool) ? item.tool : "unknown"}` : void 0;
8229
- const path43 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
8250
+ const path48 = titleFromEvent ?? toolTitleById.get(item.id) ?? "";
8230
8251
  toolTitleById.delete(item.id);
8231
8252
  toolKindById.delete(item.id);
8232
- yield { event: "tool_complete", id: item.id, kind, path: path43 };
8253
+ yield { event: "tool_complete", id: item.id, kind, path: path48 };
8233
8254
  }
8234
8255
  }
8235
8256
  }
@@ -9241,8 +9262,8 @@ function resourceNotFound(resource) {
9241
9262
  `Resource not found: ${resource}`
9242
9263
  );
9243
9264
  }
9244
- function assertAbsolutePath(path43) {
9245
- if (!isAbsolute(path43)) {
9265
+ function assertAbsolutePath(path48) {
9266
+ if (!isAbsolute(path48)) {
9246
9267
  throw invalidParams('"path" must be an absolute path');
9247
9268
  }
9248
9269
  }
@@ -10354,7 +10375,7 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
10354
10375
  }
10355
10376
  const id = readString(event.id);
10356
10377
  const kind = readString(event.kind);
10357
- const path43 = readString(event.path);
10378
+ const path48 = readString(event.path);
10358
10379
  let toolCall = id ? toolCallsById.get(id) : void 0;
10359
10380
  if (!toolCall) {
10360
10381
  toolCall = {};
@@ -10369,8 +10390,8 @@ function updateSessionFromEvent(ctx, event, toolCallsById) {
10369
10390
  if (kind) {
10370
10391
  toolCall.kind = kind;
10371
10392
  }
10372
- if (path43) {
10373
- toolCall.path = path43;
10393
+ if (path48) {
10394
+ toolCall.path = path48;
10374
10395
  }
10375
10396
  }
10376
10397
  var sessionCapture;
@@ -10859,14 +10880,14 @@ function parseDockerLocator(input) {
10859
10880
  throw new Error(`Invalid docker workspace locator "${input}".`);
10860
10881
  }
10861
10882
  const container = input.slice(0, slashIndex);
10862
- const path43 = input.slice(slashIndex);
10863
- if (container.length === 0 || path43.length === 0) {
10883
+ const path48 = input.slice(slashIndex);
10884
+ if (container.length === 0 || path48.length === 0) {
10864
10885
  throw new Error(`Invalid docker workspace locator "${input}".`);
10865
10886
  }
10866
10887
  return {
10867
10888
  scheme: "docker",
10868
10889
  container,
10869
- path: path43
10890
+ path: path48
10870
10891
  };
10871
10892
  }
10872
10893
  function splitOnce(input, separator) {
@@ -12743,21 +12764,21 @@ function createSdkContainer(options) {
12743
12764
  });
12744
12765
  loggerFactory.setErrorLogger(errorLogger);
12745
12766
  const asyncFs = {
12746
- readFile: ((path43, encoding) => {
12767
+ readFile: ((path48, encoding) => {
12747
12768
  if (encoding) {
12748
- return fs2.readFile(path43, encoding);
12769
+ return fs2.readFile(path48, encoding);
12749
12770
  }
12750
- return fs2.readFile(path43);
12771
+ return fs2.readFile(path48);
12751
12772
  }),
12752
- writeFile: (path43, data, opts) => fs2.writeFile(path43, data, opts),
12753
- mkdir: (path43, opts) => fs2.mkdir(path43, opts).then(() => {
12773
+ writeFile: (path48, data, opts) => fs2.writeFile(path48, data, opts),
12774
+ mkdir: (path48, opts) => fs2.mkdir(path48, opts).then(() => {
12754
12775
  }),
12755
- stat: (path43) => fs2.stat(path43),
12756
- rm: (path43, opts) => fs2.rm(path43, opts),
12757
- unlink: (path43) => fs2.unlink(path43),
12758
- readdir: (path43) => fs2.readdir(path43),
12776
+ stat: (path48) => fs2.stat(path48),
12777
+ rm: (path48, opts) => fs2.rm(path48, opts),
12778
+ unlink: (path48) => fs2.unlink(path48),
12779
+ readdir: (path48) => fs2.readdir(path48),
12759
12780
  copyFile: (src, dest) => fs2.copyFile(src, dest),
12760
- chmod: (path43, mode) => fs2.chmod(path43, mode)
12781
+ chmod: (path48, mode) => fs2.chmod(path48, mode)
12761
12782
  };
12762
12783
  const contextFactory = createCommandContextFactory({ fs: asyncFs });
12763
12784
  const authFs = {
@@ -13390,11 +13411,11 @@ function createDefaultFs() {
13390
13411
  readFile: fsPromises2.readFile,
13391
13412
  readdir: fsPromises2.readdir,
13392
13413
  stat: async (filePath) => {
13393
- const stat13 = await fsPromises2.stat(filePath);
13414
+ const stat14 = await fsPromises2.stat(filePath);
13394
13415
  return {
13395
- isFile: () => stat13.isFile(),
13396
- isDirectory: () => stat13.isDirectory(),
13397
- mtimeMs: stat13.mtimeMs
13416
+ isFile: () => stat14.isFile(),
13417
+ isDirectory: () => stat14.isDirectory(),
13418
+ mtimeMs: stat14.mtimeMs
13398
13419
  };
13399
13420
  }
13400
13421
  };
@@ -13421,8 +13442,8 @@ function countCompletedTasks(planPath, content) {
13421
13442
  async function ensurePlanExists(fs3, cwd, planPath) {
13422
13443
  const absolutePath = path15.isAbsolute(planPath) ? planPath : path15.resolve(cwd, planPath);
13423
13444
  try {
13424
- const stat13 = await fs3.stat(absolutePath);
13425
- if (!stat13.isFile()) {
13445
+ const stat14 = await fs3.stat(absolutePath);
13446
+ if (!stat14.isFile()) {
13426
13447
  throw new Error(`Plan not found at "${planPath}".`);
13427
13448
  }
13428
13449
  } catch (error2) {
@@ -13448,8 +13469,8 @@ async function scanPlansDir(fs3, plansDir, displayPrefix) {
13448
13469
  continue;
13449
13470
  }
13450
13471
  const absolutePath = path15.join(plansDir, entry);
13451
- const stat13 = await fs3.stat(absolutePath);
13452
- if (!stat13.isFile()) {
13472
+ const stat14 = await fs3.stat(absolutePath);
13473
+ if (!stat14.isFile()) {
13453
13474
  continue;
13454
13475
  }
13455
13476
  const displayPath = path15.join(displayPrefix, entry);
@@ -13491,8 +13512,8 @@ async function resolvePlanDirectory(options) {
13491
13512
  const fs3 = options.fs ?? createDefaultFs();
13492
13513
  const projectDir = path15.join(options.cwd, ".poe-code");
13493
13514
  try {
13494
- const stat13 = await fs3.stat(projectDir);
13495
- if (stat13.isDirectory()) {
13515
+ const stat14 = await fs3.stat(projectDir);
13516
+ if (stat14.isDirectory()) {
13496
13517
  return path15.join(options.cwd, ".poe-code", "pipeline", "plans");
13497
13518
  }
13498
13519
  } catch {
@@ -13707,11 +13728,11 @@ function createDefaultFs2() {
13707
13728
  },
13708
13729
  rmdir: fsPromises3.rmdir,
13709
13730
  stat: async (filePath) => {
13710
- const stat13 = await fsPromises3.stat(filePath);
13731
+ const stat14 = await fsPromises3.stat(filePath);
13711
13732
  return {
13712
- isFile: () => stat13.isFile(),
13713
- isDirectory: () => stat13.isDirectory(),
13714
- mtimeMs: stat13.mtimeMs
13733
+ isFile: () => stat14.isFile(),
13734
+ isDirectory: () => stat14.isDirectory(),
13735
+ mtimeMs: stat14.mtimeMs
13715
13736
  };
13716
13737
  }
13717
13738
  };
@@ -13744,8 +13765,8 @@ async function lockFile(filePath, options = {}) {
13744
13765
  if (!error2 || typeof error2 !== "object" || !("code" in error2) || error2.code !== "EEXIST") {
13745
13766
  throw error2;
13746
13767
  }
13747
- const stat13 = await fs3.stat(lockPath);
13748
- if (Date.now() - stat13.mtimeMs > staleMs) {
13768
+ const stat14 = await fs3.stat(lockPath);
13769
+ if (Date.now() - stat14.mtimeMs > staleMs) {
13749
13770
  await fs3.rmdir(lockPath);
13750
13771
  continue;
13751
13772
  }
@@ -13771,11 +13792,11 @@ function createDefaultFs3() {
13771
13792
  writeFile: fsPromises4.writeFile,
13772
13793
  readdir: fsPromises4.readdir,
13773
13794
  stat: async (filePath) => {
13774
- const stat13 = await fsPromises4.stat(filePath);
13795
+ const stat14 = await fsPromises4.stat(filePath);
13775
13796
  return {
13776
- isFile: () => stat13.isFile(),
13777
- isDirectory: () => stat13.isDirectory(),
13778
- mtimeMs: stat13.mtimeMs
13797
+ isFile: () => stat14.isFile(),
13798
+ isDirectory: () => stat14.isDirectory(),
13799
+ mtimeMs: stat14.mtimeMs
13779
13800
  };
13780
13801
  },
13781
13802
  mkdir: async (filePath, options) => {
@@ -14237,8 +14258,8 @@ async function removeDirectory2(fs3, directoryPath) {
14237
14258
  }
14238
14259
  for (const entry of entries) {
14239
14260
  const entryPath = path18.join(directoryPath, entry);
14240
- const stat13 = await fs3.stat(entryPath);
14241
- if (stat13.isFile()) {
14261
+ const stat14 = await fs3.stat(entryPath);
14262
+ if (stat14.isFile()) {
14242
14263
  await fs3.rm(entryPath, { force: true });
14243
14264
  continue;
14244
14265
  }
@@ -14284,8 +14305,8 @@ function createStateStore(stateDir, fs3 = nodeFs2) {
14284
14305
  for (const entry of [...entries].sort()) {
14285
14306
  const entryPath = path18.join(stateDir, entry);
14286
14307
  try {
14287
- const stat13 = await fs3.stat(entryPath);
14288
- if (stat13.isFile()) {
14308
+ const stat14 = await fs3.stat(entryPath);
14309
+ if (stat14.isFile()) {
14289
14310
  continue;
14290
14311
  }
14291
14312
  } catch (error2) {
@@ -15691,8 +15712,8 @@ async function listIds(fs3, baseDir) {
15691
15712
  for (const entry of entries) {
15692
15713
  const entryPath = path22.join(baseDir, entry);
15693
15714
  try {
15694
- const stat13 = await fs3.stat(entryPath);
15695
- if (!stat13.isFile()) {
15715
+ const stat14 = await fs3.stat(entryPath);
15716
+ if (!stat14.isFile()) {
15696
15717
  ids.push(entry);
15697
15718
  }
15698
15719
  } catch (error2) {
@@ -15945,10 +15966,10 @@ function createDefaultFs4() {
15945
15966
  return {
15946
15967
  readdir: fsPromises5.readdir,
15947
15968
  stat: async (filePath) => {
15948
- const stat13 = await fsPromises5.stat(filePath);
15969
+ const stat14 = await fsPromises5.stat(filePath);
15949
15970
  return {
15950
- isFile: () => stat13.isFile(),
15951
- mtimeMs: stat13.mtimeMs
15971
+ isFile: () => stat14.isFile(),
15972
+ mtimeMs: stat14.mtimeMs
15952
15973
  };
15953
15974
  }
15954
15975
  };
@@ -15975,8 +15996,8 @@ async function scanDir(fs3, absoluteDir, displayDir) {
15975
15996
  continue;
15976
15997
  }
15977
15998
  const absolutePath = path23.join(absoluteDir, entry);
15978
- const stat13 = await fs3.stat(absolutePath);
15979
- if (!stat13.isFile()) {
15999
+ const stat14 = await fs3.stat(absolutePath);
16000
+ if (!stat14.isFile()) {
15980
16001
  continue;
15981
16002
  }
15982
16003
  const displayPath = path23.join(displayDir, entry);
@@ -16149,10 +16170,10 @@ function createDefaultFs5() {
16149
16170
  writeFile: (filePath, content) => fsPromises6.writeFile(filePath, content, "utf8"),
16150
16171
  readdir: fsPromises6.readdir,
16151
16172
  stat: async (filePath) => {
16152
- const stat13 = await fsPromises6.stat(filePath);
16173
+ const stat14 = await fsPromises6.stat(filePath);
16153
16174
  return {
16154
- isFile: () => stat13.isFile(),
16155
- mtimeMs: stat13.mtimeMs
16175
+ isFile: () => stat14.isFile(),
16176
+ mtimeMs: stat14.mtimeMs
16156
16177
  };
16157
16178
  },
16158
16179
  mkdir: async (filePath, options) => {
@@ -16679,10 +16700,10 @@ function createDefaultFs6() {
16679
16700
  writeFile: (filePath, content) => fsPromises7.writeFile(filePath, content, "utf8"),
16680
16701
  readdir: fsPromises7.readdir,
16681
16702
  stat: async (filePath) => {
16682
- const stat13 = await fsPromises7.stat(filePath);
16703
+ const stat14 = await fsPromises7.stat(filePath);
16683
16704
  return {
16684
- isFile: () => stat13.isFile(),
16685
- mtimeMs: stat13.mtimeMs
16705
+ isFile: () => stat14.isFile(),
16706
+ mtimeMs: stat14.mtimeMs
16686
16707
  };
16687
16708
  },
16688
16709
  mkdir: async (filePath, options) => {
@@ -17000,10 +17021,10 @@ function createDefaultFs7() {
17000
17021
  },
17001
17022
  readdir: fsPromises8.readdir,
17002
17023
  stat: async (filePath) => {
17003
- const stat13 = await fsPromises8.stat(filePath);
17024
+ const stat14 = await fsPromises8.stat(filePath);
17004
17025
  return {
17005
- isFile: () => stat13.isFile(),
17006
- mtimeMs: stat13.mtimeMs
17026
+ isFile: () => stat14.isFile(),
17027
+ mtimeMs: stat14.mtimeMs
17007
17028
  };
17008
17029
  },
17009
17030
  mkdir: async (filePath, options) => {
@@ -23933,11 +23954,11 @@ function formatSegment(segment, casing) {
23933
23954
  const separator = casing === "snake" ? "_" : "-";
23934
23955
  return splitWords(segment).join(separator);
23935
23956
  }
23936
- function toOptionFlag(path43, casing) {
23937
- return `--${path43.map((segment) => formatSegment(segment, casing)).join(".")}`;
23957
+ function toOptionFlag(path48, casing) {
23958
+ return `--${path48.map((segment) => formatSegment(segment, casing)).join(".")}`;
23938
23959
  }
23939
- function toOptionAttribute(path43, casing) {
23940
- return path43.map((segment) => {
23960
+ function toOptionAttribute(path48, casing) {
23961
+ return path48.map((segment) => {
23941
23962
  const formatted = formatSegment(segment, casing);
23942
23963
  if (casing === "snake") {
23943
23964
  return formatted;
@@ -23948,13 +23969,13 @@ function toOptionAttribute(path43, casing) {
23948
23969
  ).join("");
23949
23970
  }).join(".");
23950
23971
  }
23951
- function toDisplayPath(path43) {
23952
- return path43.join(".");
23972
+ function toDisplayPath(path48) {
23973
+ return path48.join(".");
23953
23974
  }
23954
- function collectFields(schema, casing, path43 = [], inheritedOptional = false) {
23975
+ function collectFields(schema, casing, path48 = [], inheritedOptional = false) {
23955
23976
  const fields = [];
23956
23977
  for (const [key, rawChildSchema] of Object.entries(schema.shape)) {
23957
- const nextPath = [...path43, key];
23978
+ const nextPath = [...path48, key];
23958
23979
  const optional = inheritedOptional || rawChildSchema.kind === "optional";
23959
23980
  const childSchema = unwrapOptional(rawChildSchema);
23960
23981
  if (childSchema.kind === "object") {
@@ -23977,9 +23998,9 @@ function collectFields(schema, casing, path43 = [], inheritedOptional = false) {
23977
23998
  }
23978
23999
  return fields;
23979
24000
  }
23980
- function toCommanderOptionAttribute(path43, casing) {
23981
- const optionAttribute = toOptionAttribute(path43, casing);
23982
- const optionFlag = toOptionFlag(path43, casing);
24001
+ function toCommanderOptionAttribute(path48, casing) {
24002
+ const optionAttribute = toOptionAttribute(path48, casing);
24003
+ const optionFlag = toOptionFlag(path48, casing);
23983
24004
  if (!GLOBAL_LONG_OPTION_FLAGS.has(optionFlag)) {
23984
24005
  return optionAttribute;
23985
24006
  }
@@ -24427,10 +24448,10 @@ function addGlobalOptions(command) {
24427
24448
  throw new InvalidArgumentError('Invalid value for "--output". Expected one of: rich, md, json.');
24428
24449
  }).option("--verbose", "Print stack traces for unexpected errors.");
24429
24450
  }
24430
- function setNestedValue(target, path43, value) {
24451
+ function setNestedValue(target, path48, value) {
24431
24452
  let cursor = target;
24432
- for (let index = 0; index < path43.length - 1; index += 1) {
24433
- const segment = path43[index] ?? "";
24453
+ for (let index = 0; index < path48.length - 1; index += 1) {
24454
+ const segment = path48[index] ?? "";
24434
24455
  const existing = cursor[segment];
24435
24456
  if (typeof existing === "object" && existing !== null) {
24436
24457
  cursor = existing;
@@ -24440,7 +24461,7 @@ function setNestedValue(target, path43, value) {
24440
24461
  cursor[segment] = next;
24441
24462
  cursor = next;
24442
24463
  }
24443
- const leaf = path43[path43.length - 1];
24464
+ const leaf = path48[path48.length - 1];
24444
24465
  if (leaf !== void 0) {
24445
24466
  cursor[leaf] = value;
24446
24467
  }
@@ -24530,13 +24551,13 @@ async function withOutputFormat2(output, fn) {
24530
24551
  }
24531
24552
  function createFs() {
24532
24553
  return {
24533
- readFile: async (path43, encoding = "utf8") => readFile12(path43, { encoding }),
24534
- writeFile: async (path43, contents) => {
24535
- await writeFile7(path43, contents);
24554
+ readFile: async (path48, encoding = "utf8") => readFile12(path48, { encoding }),
24555
+ writeFile: async (path48, contents) => {
24556
+ await writeFile7(path48, contents);
24536
24557
  },
24537
- exists: async (path43) => {
24558
+ exists: async (path48) => {
24538
24559
  try {
24539
- await access2(path43);
24560
+ await access2(path48);
24540
24561
  return true;
24541
24562
  } catch {
24542
24563
  return false;
@@ -24557,9 +24578,9 @@ function isPlainObject(value) {
24557
24578
  function hasFieldValue(value) {
24558
24579
  return value !== void 0;
24559
24580
  }
24560
- function hasNestedField(fields, path43) {
24581
+ function hasNestedField(fields, path48) {
24561
24582
  return fields.some(
24562
- (field) => path43.length < field.path.length && path43.every((segment, index) => field.path[index] === segment)
24583
+ (field) => path48.length < field.path.length && path48.every((segment, index) => field.path[index] === segment)
24563
24584
  );
24564
24585
  }
24565
24586
  function describeExpectedPresetValue(schema) {
@@ -24643,9 +24664,9 @@ async function loadPresetValues(fields, presetPath) {
24643
24664
  }
24644
24665
  const fieldByPath = new Map(fields.map((field) => [field.displayPath, field]));
24645
24666
  const presetValues = {};
24646
- function visitObject(current, path43) {
24667
+ function visitObject(current, path48) {
24647
24668
  for (const [key, value] of Object.entries(current)) {
24648
- const nextPath = [...path43, key];
24669
+ const nextPath = [...path48, key];
24649
24670
  const displayPath = toDisplayPath(nextPath);
24650
24671
  const field = fieldByPath.get(displayPath);
24651
24672
  if (field !== void 0) {
@@ -28899,23 +28920,24 @@ var init_configs3 = __esm({
28899
28920
  }
28900
28921
  });
28901
28922
 
28923
+ // packages/agent-skill-config/src/templates/poe-generate.md
28924
+ var poe_generate_default;
28925
+ var init_poe_generate = __esm({
28926
+ "packages/agent-skill-config/src/templates/poe-generate.md"() {
28927
+ poe_generate_default = '---\nname: poe-generate\ndescription: \'Poe code generation skill\'\n---\n\n# poe-code generate\n\nUse `poe-code generate` to create text, images, audio, or video via the Poe API.\n\n## Text generation\n\n```bash\npoe-code generate "Write a short function that parses a JSON string safely."\n```\n\nSpecify the model/bot:\n\n```bash\n# CLI option\npoe-code generate --model "gpt-4.1" "Summarize this codebase change."\n\n# Some agent runtimes call the model selector `--bot`\npoe-code generate --bot "gpt-4.1" "Summarize this codebase change."\n```\n\n## Media generation\n\nThe CLI supports media generation as subcommands:\n\n```bash\npoe-code generate image "A 3D render of a rubber duck wearing sunglasses" --model "gpt-image-1" -o duck.png\npoe-code generate video "A cinematic timelapse of a city at night" --model "veo" -o city.mp4\npoe-code generate audio "A calm 10 second lo-fi beat" --model "audio-model" -o beat.wav\n```\n\nSome agent runtimes expose the same media types as flags. If available, these are equivalent:\n\n```bash\npoe-code generate --image "A 3D render of a rubber duck wearing sunglasses" --bot "gpt-image-1" -o duck.png\npoe-code generate --video "A cinematic timelapse of a city at night" --bot "veo" -o city.mp4\npoe-code generate --audio "A calm 10 second lo-fi beat" --bot "audio-model" -o beat.wav\n```\n\n## Tips\n\n- Use `--param key=value` to pass provider/model parameters (repeatable).\n- Use `--output <path>` (or `-o`) for media outputs.\n';
28928
+ }
28929
+ });
28930
+
28931
+ // packages/agent-skill-config/src/templates/terminal-pilot.md
28932
+ var terminal_pilot_default;
28933
+ var init_terminal_pilot = __esm({
28934
+ "packages/agent-skill-config/src/templates/terminal-pilot.md"() {
28935
+ terminal_pilot_default = "---\nname: terminal-pilot\ndescription: 'Terminal automation skill using the terminal-pilot CLI'\n---\n\n# Terminal Pilot\n\nUse the `terminal-pilot` CLI when you need to automate or inspect interactive\nCLI applications through a real PTY session.\n\n## Commands\n\n- `terminal-pilot create-session` - start a PTY-backed command\n- `terminal-pilot fill` - paste text into a session\n- `terminal-pilot type` - type character-by-character for TUIs and readline\n- `terminal-pilot press-key` - send named keys such as `Enter` or `ArrowDown`\n- `terminal-pilot wait-for` - wait for terminal output to match a pattern\n- `terminal-pilot wait-for-exit` - block until a session exits\n- `terminal-pilot read-screen` - inspect the current visible terminal screen\n- `terminal-pilot read-history` - read scrollback output\n- `terminal-pilot list-sessions` - list active sessions\n- `terminal-pilot close-session` - close a session and return its exit code\n\n## Examples\n\n```bash\nterminal-pilot --help\nterminal-pilot create-session --help\nterminal-pilot read-screen --help\n```\n\nUse JSON output when another tool or script needs to read the result:\n\n```bash\nterminal-pilot list-sessions --output json\nterminal-pilot read-screen --session s1 --output json\n```\n\n## Tips\n\n- Use `fill` for pasted text and multi-line input.\n- Use `type` when the app reacts to individual keystrokes.\n- Use `press-key` for Enter, Tab, arrow keys, Escape, and control-key chords.\n- Use `wait-for --literal` for exact string matching.\n- Default terminal size is 120x40.\n";
28936
+ }
28937
+ });
28938
+
28902
28939
  // packages/agent-skill-config/src/templates.ts
28903
- import { readFile as readFile13 } from "node:fs/promises";
28904
- async function getTemplates() {
28905
- if (templatesCache) {
28906
- return templatesCache;
28907
- }
28908
- const entries = await Promise.all(
28909
- TEMPLATE_NAMES.map(async (name) => {
28910
- const url = new URL(`./templates/${name}`, import.meta.url);
28911
- return [name, await readFile13(url, "utf8")];
28912
- })
28913
- );
28914
- templatesCache = Object.fromEntries(entries);
28915
- return templatesCache;
28916
- }
28917
28940
  async function loadTemplate2(templateId) {
28918
- const templates = await getTemplates();
28919
28941
  const template = templates[templateId];
28920
28942
  if (!template) {
28921
28943
  throw new Error(`Template not found: ${templateId}`);
@@ -28925,12 +28947,16 @@ async function loadTemplate2(templateId) {
28925
28947
  function createTemplateLoader() {
28926
28948
  return loadTemplate2;
28927
28949
  }
28928
- var TEMPLATE_NAMES, templatesCache;
28950
+ var templates;
28929
28951
  var init_templates = __esm({
28930
28952
  "packages/agent-skill-config/src/templates.ts"() {
28931
28953
  "use strict";
28932
- TEMPLATE_NAMES = ["poe-generate.md", "terminal-pilot.md"];
28933
- templatesCache = null;
28954
+ init_poe_generate();
28955
+ init_terminal_pilot();
28956
+ templates = {
28957
+ "poe-generate.md": poe_generate_default,
28958
+ "terminal-pilot.md": terminal_pilot_default
28959
+ };
28934
28960
  }
28935
28961
  });
28936
28962
 
@@ -29943,7 +29969,7 @@ var init_models2 = __esm({
29943
29969
 
29944
29970
  // src/cli/commands/pipeline.ts
29945
29971
  import path40 from "node:path";
29946
- import { readFile as readFile14, stat as stat11 } from "node:fs/promises";
29972
+ import { readFile as readFile13, stat as stat11 } from "node:fs/promises";
29947
29973
  import { fileURLToPath as fileURLToPath7 } from "node:url";
29948
29974
  async function resolvePipelinePlanDirectory(container) {
29949
29975
  const configDoc = await readMergedDocument(
@@ -30013,8 +30039,8 @@ async function loadPipelineTemplates() {
30013
30039
  continue;
30014
30040
  }
30015
30041
  const [skillPlan, steps] = await Promise.all([
30016
- readFile14(path40.join(templateRoot, "SKILL_plan.md"), "utf8"),
30017
- readFile14(path40.join(templateRoot, "steps.yaml.hbs"), "utf8")
30042
+ readFile13(path40.join(templateRoot, "SKILL_plan.md"), "utf8"),
30043
+ readFile13(path40.join(templateRoot, "steps.yaml.hbs"), "utf8")
30018
30044
  ]);
30019
30045
  pipelineTemplatesCache = { skillPlan, steps };
30020
30046
  return pipelineTemplatesCache;
@@ -30348,12 +30374,12 @@ function registerPipelineCommand(program, container) {
30348
30374
  scope = selected;
30349
30375
  }
30350
30376
  resources.logger.intro(`pipeline install (${support.id}, ${scope})`);
30351
- const templates = await loadPipelineTemplates();
30377
+ const templates2 = await loadPipelineTemplates();
30352
30378
  const skillResult = await installSkill(
30353
30379
  support.id,
30354
30380
  {
30355
30381
  name: "poe-code-pipeline-plan",
30356
- content: templates.skillPlan
30382
+ content: templates2.skillPlan
30357
30383
  },
30358
30384
  {
30359
30385
  fs: container.fs,
@@ -30394,7 +30420,7 @@ function registerPipelineCommand(program, container) {
30394
30420
  await container.fs.mkdir(path40.dirname(pipelinePaths.stepsPath), {
30395
30421
  recursive: true
30396
30422
  });
30397
- await container.fs.writeFile(pipelinePaths.stepsPath, templates.steps, {
30423
+ await container.fs.writeFile(pipelinePaths.stepsPath, templates2.steps, {
30398
30424
  encoding: "utf8"
30399
30425
  });
30400
30426
  resources.logger.info(
@@ -30429,8 +30455,828 @@ var init_pipeline3 = __esm({
30429
30455
  }
30430
30456
  });
30431
30457
 
30432
- // src/cli/commands/ralph.ts
30458
+ // packages/plan-browser/src/format.ts
30433
30459
  import path41 from "node:path";
30460
+ function isPipelineTaskDone(task) {
30461
+ if (typeof task.status === "string") {
30462
+ return task.status === "done";
30463
+ }
30464
+ return Object.values(task.status).every((status) => status === "done");
30465
+ }
30466
+ function formatPipelineProgress(content) {
30467
+ const plan = parsePlan(content);
30468
+ const done = plan.tasks.filter((task) => isPipelineTaskDone(task)).length;
30469
+ return `${done}/${plan.tasks.length} done`;
30470
+ }
30471
+ function formatRalphDetail(frontmatter) {
30472
+ const parts = [];
30473
+ if (frontmatter.agent !== void 0) {
30474
+ parts.push(Array.isArray(frontmatter.agent) ? frontmatter.agent.join(", ") : frontmatter.agent);
30475
+ }
30476
+ if (frontmatter.iterations !== void 0) {
30477
+ parts.push(`\xD7${frontmatter.iterations}`);
30478
+ }
30479
+ if (frontmatter.status.state !== "open" || frontmatter.status.iteration > 0) {
30480
+ parts.push(`${frontmatter.status.state} ${frontmatter.status.iteration}`);
30481
+ } else {
30482
+ parts.push("open");
30483
+ }
30484
+ return parts.join(" \xB7 ");
30485
+ }
30486
+ function formatExperimentDetail(frontmatter, state) {
30487
+ const parts = [];
30488
+ if (frontmatter.agent !== void 0) {
30489
+ parts.push(Array.isArray(frontmatter.agent) ? frontmatter.agent.join(", ") : frontmatter.agent);
30490
+ }
30491
+ const metrics = frontmatter.metric === void 0 ? [] : Array.isArray(frontmatter.metric) ? frontmatter.metric : [frontmatter.metric];
30492
+ if (metrics.length > 0) {
30493
+ const directions = Array.from(new Set(metrics.map((metric) => metric.direction)));
30494
+ parts.push(directions.join("/"));
30495
+ }
30496
+ parts.push(state);
30497
+ return parts.join(" \xB7 ");
30498
+ }
30499
+ function getLastExperimentState(journalContent) {
30500
+ const lines = journalContent.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
30501
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
30502
+ try {
30503
+ const parsed = JSON.parse(lines[index]);
30504
+ if (typeof parsed.status === "string" && parsed.status.length > 0) {
30505
+ return parsed.status;
30506
+ }
30507
+ } catch {
30508
+ continue;
30509
+ }
30510
+ }
30511
+ return "open";
30512
+ }
30513
+ function deriveMarkdownTitle(content, fallbackName) {
30514
+ const heading = content.split("\n").map((line) => line.trim()).find((line) => line.startsWith("# "));
30515
+ return heading ? heading.slice(2).trim() || fallbackName : fallbackName;
30516
+ }
30517
+ function formatPipelineTaskDetails(task) {
30518
+ if (typeof task.status === "string") {
30519
+ return null;
30520
+ }
30521
+ const entries = Object.entries(task.status).map(([name, status]) => `${name}=${status}`);
30522
+ return entries.length > 0 ? `Step status: ${entries.join(", ")}` : null;
30523
+ }
30524
+ function formatPipelinePlanMarkdown(options) {
30525
+ const plan = parsePlan(options.content);
30526
+ const lines = [
30527
+ `# ${options.title}`,
30528
+ "",
30529
+ `Status: ${formatPipelineProgress(options.content)}`,
30530
+ "",
30531
+ "## Tasks",
30532
+ ""
30533
+ ];
30534
+ for (const task of plan.tasks) {
30535
+ const mark = isPipelineTaskDone(task) ? "x" : " ";
30536
+ lines.push(`- [${mark}] ${task.title} (\`${task.id}\`)`);
30537
+ const detail = formatPipelineTaskDetails(task);
30538
+ if (detail) {
30539
+ lines.push(` - ${detail}`);
30540
+ }
30541
+ for (const promptLine of task.prompt.split("\n")) {
30542
+ lines.push(` > ${promptLine}`);
30543
+ }
30544
+ lines.push("");
30545
+ }
30546
+ return lines.join("\n").trimEnd();
30547
+ }
30548
+ function resolveExperimentJournalPath(absolutePath) {
30549
+ return path41.join(
30550
+ path41.dirname(absolutePath),
30551
+ `${path41.basename(absolutePath, path41.extname(absolutePath))}.journal.jsonl`
30552
+ );
30553
+ }
30554
+ async function readExperimentState(fs3, absolutePath) {
30555
+ try {
30556
+ const content = await fs3.readFile(resolveExperimentJournalPath(absolutePath), "utf8");
30557
+ return getLastExperimentState(content);
30558
+ } catch {
30559
+ return "open";
30560
+ }
30561
+ }
30562
+ async function loadPlanPreviewMarkdown(entry, fs3) {
30563
+ const content = await fs3.readFile(entry.absolutePath, "utf8");
30564
+ if (entry.source === "pipeline") {
30565
+ return formatPipelinePlanMarkdown({
30566
+ title: entry.title,
30567
+ content
30568
+ });
30569
+ }
30570
+ return content;
30571
+ }
30572
+ async function readPlanMetadata(options) {
30573
+ const content = await options.fs.readFile(options.absolutePath, "utf8");
30574
+ const fallbackName = path41.basename(options.path);
30575
+ if (options.source === "pipeline") {
30576
+ return {
30577
+ title: fallbackName,
30578
+ status: formatPipelineProgress(content),
30579
+ format: "yaml"
30580
+ };
30581
+ }
30582
+ if (options.source === "ralph") {
30583
+ const parsed2 = parseFrontmatter(content);
30584
+ return {
30585
+ title: deriveMarkdownTitle(parsed2.body, fallbackName),
30586
+ status: formatRalphDetail(parsed2.data),
30587
+ format: "markdown"
30588
+ };
30589
+ }
30590
+ const parsed = parseExperimentFrontmatter(content);
30591
+ const state = await readExperimentState(options.fs, options.absolutePath);
30592
+ return {
30593
+ title: deriveMarkdownTitle(parsed.body, fallbackName),
30594
+ status: formatExperimentDetail(parsed.frontmatter, state),
30595
+ format: "markdown"
30596
+ };
30597
+ }
30598
+ var init_format = __esm({
30599
+ "packages/plan-browser/src/format.ts"() {
30600
+ "use strict";
30601
+ init_src10();
30602
+ init_src14();
30603
+ init_src13();
30604
+ }
30605
+ });
30606
+
30607
+ // packages/plan-browser/src/discovery.ts
30608
+ import path42 from "node:path";
30609
+ import * as fsPromises10 from "node:fs/promises";
30610
+ function createDefaultFs8() {
30611
+ return {
30612
+ readFile: fsPromises10.readFile,
30613
+ writeFile: fsPromises10.writeFile,
30614
+ readdir: fsPromises10.readdir,
30615
+ stat: async (filePath) => {
30616
+ const stat14 = await fsPromises10.stat(filePath);
30617
+ return {
30618
+ isFile: () => stat14.isFile(),
30619
+ isDirectory: () => stat14.isDirectory(),
30620
+ mtimeMs: stat14.mtimeMs
30621
+ };
30622
+ },
30623
+ mkdir: async (directoryPath, mkdirOptions) => {
30624
+ await fsPromises10.mkdir(directoryPath, mkdirOptions);
30625
+ },
30626
+ rename: fsPromises10.rename,
30627
+ unlink: fsPromises10.unlink
30628
+ };
30629
+ }
30630
+ function isNotFound4(error2) {
30631
+ return !!error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT";
30632
+ }
30633
+ function resolveAbsoluteDirectory3(dir, cwd, homeDir) {
30634
+ if (dir.startsWith("~/")) {
30635
+ return path42.join(homeDir, dir.slice(2));
30636
+ }
30637
+ return path42.isAbsolute(dir) ? dir : path42.resolve(cwd, dir);
30638
+ }
30639
+ function resolveAbsoluteDisplayPath(displayPath, cwd, homeDir) {
30640
+ if (displayPath.startsWith("~/")) {
30641
+ return path42.join(homeDir, displayPath.slice(2));
30642
+ }
30643
+ return path42.isAbsolute(displayPath) ? displayPath : path42.resolve(cwd, displayPath);
30644
+ }
30645
+ function isPipelinePlanFile(name) {
30646
+ const lower = name.toLowerCase();
30647
+ return lower.startsWith("plan") && (lower.endsWith(".yaml") || lower.endsWith(".yml"));
30648
+ }
30649
+ function isMarkdownFile2(name) {
30650
+ return name.toLowerCase().endsWith(".md");
30651
+ }
30652
+ async function resolvePlanDirectorySetting(options) {
30653
+ const envValue = options.variables?.[options.envName]?.trim();
30654
+ if (envValue) {
30655
+ return envValue;
30656
+ }
30657
+ const document = await readMergedDocument(
30658
+ options.fs,
30659
+ options.configPath,
30660
+ options.projectConfigPath
30661
+ );
30662
+ const configured = document[options.scope]?.plan_directory;
30663
+ return typeof configured === "string" && configured.trim().length > 0 ? configured.trim() : void 0;
30664
+ }
30665
+ async function scanDirectory(options) {
30666
+ let entries;
30667
+ try {
30668
+ entries = await options.fs.readdir(options.absoluteDir);
30669
+ } catch (error2) {
30670
+ if (isNotFound4(error2)) {
30671
+ return [];
30672
+ }
30673
+ throw error2;
30674
+ }
30675
+ const plans = [];
30676
+ for (const name of entries) {
30677
+ if (!options.include(name)) {
30678
+ continue;
30679
+ }
30680
+ const absolutePath = path42.join(options.absoluteDir, name);
30681
+ const stat14 = await options.fs.stat(absolutePath);
30682
+ if (!stat14.isFile()) {
30683
+ continue;
30684
+ }
30685
+ const displayPath = path42.join(options.displayDir, name);
30686
+ const metadata = await readPlanMetadata({
30687
+ source: options.source,
30688
+ absolutePath,
30689
+ path: displayPath,
30690
+ fs: options.fs
30691
+ });
30692
+ plans.push({
30693
+ path: displayPath,
30694
+ absolutePath: resolveAbsoluteDisplayPath(displayPath, options.cwd, options.homeDir),
30695
+ source: options.source,
30696
+ format: metadata.format,
30697
+ title: metadata.title,
30698
+ status: metadata.status,
30699
+ updatedAt: stat14.mtimeMs
30700
+ });
30701
+ }
30702
+ return plans;
30703
+ }
30704
+ async function discoverPipelinePlans(options) {
30705
+ const configuredDir = await resolvePlanDirectorySetting({
30706
+ fs: options.fs,
30707
+ configPath: options.configPath,
30708
+ projectConfigPath: options.projectConfigPath,
30709
+ scope: "pipeline",
30710
+ envName: "POE_PIPELINE_PLAN_DIRECTORY",
30711
+ variables: options.variables
30712
+ });
30713
+ const targets = configuredDir ? [{
30714
+ absoluteDir: resolveAbsoluteDirectory3(configuredDir, options.cwd, options.homeDir),
30715
+ displayDir: configuredDir
30716
+ }] : [
30717
+ {
30718
+ absoluteDir: path42.join(options.cwd, ".poe-code", "pipeline", "plans"),
30719
+ displayDir: ".poe-code/pipeline/plans"
30720
+ },
30721
+ {
30722
+ absoluteDir: path42.join(options.homeDir, ".poe-code", "pipeline", "plans"),
30723
+ displayDir: "~/.poe-code/pipeline/plans"
30724
+ }
30725
+ ];
30726
+ const plans = await Promise.all(
30727
+ targets.map(
30728
+ (target) => scanDirectory({
30729
+ ...target,
30730
+ fs: options.fs,
30731
+ source: "pipeline",
30732
+ include: isPipelinePlanFile,
30733
+ cwd: options.cwd,
30734
+ homeDir: options.homeDir
30735
+ })
30736
+ )
30737
+ );
30738
+ return plans.flat();
30739
+ }
30740
+ async function discoverExperimentPlans(options) {
30741
+ const configuredDir = await resolvePlanDirectorySetting({
30742
+ fs: options.fs,
30743
+ configPath: options.configPath,
30744
+ projectConfigPath: options.projectConfigPath,
30745
+ scope: "experiment",
30746
+ envName: "POE_EXPERIMENT_PLAN_DIRECTORY",
30747
+ variables: options.variables
30748
+ });
30749
+ const targets = configuredDir ? [{
30750
+ absoluteDir: resolveAbsoluteDirectory3(configuredDir, options.cwd, options.homeDir),
30751
+ displayDir: configuredDir
30752
+ }] : [
30753
+ {
30754
+ absoluteDir: path42.join(options.cwd, ".poe-code", "experiments"),
30755
+ displayDir: ".poe-code/experiments"
30756
+ },
30757
+ {
30758
+ absoluteDir: path42.join(options.homeDir, ".poe-code", "experiments"),
30759
+ displayDir: "~/.poe-code/experiments"
30760
+ }
30761
+ ];
30762
+ const plans = await Promise.all(
30763
+ targets.map(
30764
+ (target) => scanDirectory({
30765
+ ...target,
30766
+ fs: options.fs,
30767
+ source: "experiment",
30768
+ include: isMarkdownFile2,
30769
+ cwd: options.cwd,
30770
+ homeDir: options.homeDir
30771
+ })
30772
+ )
30773
+ );
30774
+ return plans.flat();
30775
+ }
30776
+ async function discoverRalphPlans(options) {
30777
+ const configuredDir = await resolvePlanDirectorySetting({
30778
+ fs: options.fs,
30779
+ configPath: options.configPath,
30780
+ projectConfigPath: options.projectConfigPath,
30781
+ scope: "ralph",
30782
+ envName: "POE_RALPH_PLAN_DIRECTORY",
30783
+ variables: options.variables
30784
+ });
30785
+ const docs = await discoverDocs({
30786
+ cwd: options.cwd,
30787
+ homeDir: options.homeDir,
30788
+ planDirectory: configuredDir,
30789
+ fs: {
30790
+ readdir: options.fs.readdir,
30791
+ stat: async (filePath) => {
30792
+ const stat14 = await options.fs.stat(filePath);
30793
+ return {
30794
+ isFile: () => stat14.isFile(),
30795
+ mtimeMs: stat14.mtimeMs
30796
+ };
30797
+ }
30798
+ }
30799
+ });
30800
+ const plans = await Promise.all(
30801
+ docs.map(async (doc) => {
30802
+ const absolutePath = resolveAbsoluteDisplayPath(doc.path, options.cwd, options.homeDir);
30803
+ const stat14 = await options.fs.stat(absolutePath);
30804
+ const metadata = await readPlanMetadata({
30805
+ source: "ralph",
30806
+ absolutePath,
30807
+ path: doc.path,
30808
+ fs: options.fs
30809
+ });
30810
+ return {
30811
+ path: doc.path,
30812
+ absolutePath,
30813
+ source: "ralph",
30814
+ format: metadata.format,
30815
+ title: metadata.title,
30816
+ status: metadata.status,
30817
+ updatedAt: stat14.mtimeMs
30818
+ };
30819
+ })
30820
+ );
30821
+ return plans;
30822
+ }
30823
+ async function discoverAllPlans(options) {
30824
+ const fs3 = options.fs ?? createDefaultFs8();
30825
+ const discoverers = {
30826
+ pipeline: () => discoverPipelinePlans({ ...options, fs: fs3 }),
30827
+ experiment: () => discoverExperimentPlans({ ...options, fs: fs3 }),
30828
+ ralph: () => discoverRalphPlans({ ...options, fs: fs3 })
30829
+ };
30830
+ const sources = options.source ? [options.source] : Object.keys(discoverers);
30831
+ const results = (await Promise.all(sources.map((source) => discoverers[source]()))).flat();
30832
+ const deduped = /* @__PURE__ */ new Map();
30833
+ for (const result of results) {
30834
+ if (!deduped.has(result.absolutePath)) {
30835
+ deduped.set(result.absolutePath, result);
30836
+ }
30837
+ }
30838
+ return [...deduped.values()].sort((left, right) => {
30839
+ if (right.updatedAt !== left.updatedAt) {
30840
+ return right.updatedAt - left.updatedAt;
30841
+ }
30842
+ return left.path.localeCompare(right.path);
30843
+ });
30844
+ }
30845
+ var init_discovery3 = __esm({
30846
+ "packages/plan-browser/src/discovery.ts"() {
30847
+ "use strict";
30848
+ init_src13();
30849
+ init_src4();
30850
+ init_format();
30851
+ }
30852
+ });
30853
+
30854
+ // packages/plan-browser/src/actions.ts
30855
+ import path43 from "node:path";
30856
+ import { spawnSync as nodeSpawnSync } from "node:child_process";
30857
+ function resolveEditor2(env = process.env) {
30858
+ const editor = env.EDITOR?.trim() || env.VISUAL?.trim() || "vi";
30859
+ return editor.length > 0 ? editor : "vi";
30860
+ }
30861
+ function editPlan(absolutePath, options = {}) {
30862
+ const editor = resolveEditor2(options.env);
30863
+ const spawnSync3 = options.spawnSync ?? nodeSpawnSync;
30864
+ spawnSync3(editor, [absolutePath], { stdio: "inherit" });
30865
+ }
30866
+ async function archivePlan3(entry, fs3) {
30867
+ const archiveDir = path43.join(path43.dirname(entry.absolutePath), "archive");
30868
+ const archivedPath = path43.join(archiveDir, path43.basename(entry.absolutePath));
30869
+ await fs3.mkdir(archiveDir, { recursive: true });
30870
+ await fs3.rename(entry.absolutePath, archivedPath);
30871
+ return archivedPath;
30872
+ }
30873
+ async function deletePlan(entry, fs3) {
30874
+ await fs3.unlink(entry.absolutePath);
30875
+ }
30876
+ var init_actions = __esm({
30877
+ "packages/plan-browser/src/actions.ts"() {
30878
+ "use strict";
30879
+ }
30880
+ });
30881
+
30882
+ // packages/plan-browser/src/browser.ts
30883
+ import path44 from "node:path";
30884
+ async function runPlanBrowser(options) {
30885
+ const renderPlanPreview = async (entry) => {
30886
+ const markdown = await loadPlanPreviewMarkdown(entry, options.fs);
30887
+ process.stdout.write(`${renderMarkdown(markdown).trimEnd()}
30888
+ `);
30889
+ };
30890
+ while (true) {
30891
+ const plans = await discoverAllPlans({
30892
+ cwd: options.cwd,
30893
+ homeDir: options.homeDir,
30894
+ configPath: options.configPath,
30895
+ projectConfigPath: options.projectConfigPath,
30896
+ fs: options.fs,
30897
+ source: options.source,
30898
+ variables: options.variables
30899
+ });
30900
+ if (plans.length === 0) {
30901
+ process.stdout.write("No plans found.\n");
30902
+ return;
30903
+ }
30904
+ if (options.assumeYes) {
30905
+ const selectedPlan2 = plans[0];
30906
+ await renderPlanPreview(selectedPlan2);
30907
+ return;
30908
+ }
30909
+ const selectedPath = await select2({
30910
+ message: "Select a plan",
30911
+ options: plans.map((plan) => ({
30912
+ label: text.selectLabel(path44.basename(plan.path), plan.status),
30913
+ hint: plan.source,
30914
+ value: plan.absolutePath
30915
+ }))
30916
+ });
30917
+ if (Ct(selectedPath)) {
30918
+ return;
30919
+ }
30920
+ const selectedPlan = plans.find((plan) => plan.absolutePath === selectedPath);
30921
+ if (!selectedPlan) {
30922
+ cancel("Plan selection cancelled.");
30923
+ return;
30924
+ }
30925
+ await renderPlanPreview(selectedPlan);
30926
+ process.stdout.write("\n");
30927
+ const action = await select2({
30928
+ message: "Action",
30929
+ options: [
30930
+ { label: "Back to list", value: "back" },
30931
+ { label: "Edit in $EDITOR", value: "edit" },
30932
+ { label: "Archive", value: "archive" },
30933
+ { label: "Delete", value: "delete" }
30934
+ ]
30935
+ });
30936
+ if (Ct(action) || action === "back") {
30937
+ continue;
30938
+ }
30939
+ if (action === "edit") {
30940
+ editPlan(selectedPlan.absolutePath, {
30941
+ env: options.variables ?? process.env
30942
+ });
30943
+ continue;
30944
+ }
30945
+ if (action === "archive") {
30946
+ try {
30947
+ const confirmed = options.assumeYes || await confirmOrCancel({
30948
+ message: `Archive ${path44.basename(selectedPlan.path)}?`,
30949
+ initialValue: true
30950
+ });
30951
+ if (confirmed) {
30952
+ await archivePlan3(selectedPlan, options.fs);
30953
+ }
30954
+ } catch (error2) {
30955
+ if (!(error2 instanceof PromptCancelledError)) {
30956
+ throw error2;
30957
+ }
30958
+ }
30959
+ continue;
30960
+ }
30961
+ try {
30962
+ const confirmed = options.assumeYes || await confirmOrCancel({
30963
+ message: `Permanently delete ${path44.basename(selectedPlan.path)}?`,
30964
+ initialValue: true
30965
+ });
30966
+ if (confirmed) {
30967
+ await deletePlan(selectedPlan, options.fs);
30968
+ }
30969
+ } catch (error2) {
30970
+ if (!(error2 instanceof PromptCancelledError)) {
30971
+ throw error2;
30972
+ }
30973
+ }
30974
+ }
30975
+ }
30976
+ var init_browser = __esm({
30977
+ "packages/plan-browser/src/browser.ts"() {
30978
+ "use strict";
30979
+ init_src5();
30980
+ init_src5();
30981
+ init_actions();
30982
+ init_discovery3();
30983
+ init_format();
30984
+ }
30985
+ });
30986
+
30987
+ // packages/plan-browser/src/index.ts
30988
+ var init_src23 = __esm({
30989
+ "packages/plan-browser/src/index.ts"() {
30990
+ "use strict";
30991
+ init_discovery3();
30992
+ init_actions();
30993
+ init_format();
30994
+ init_browser();
30995
+ }
30996
+ });
30997
+
30998
+ // src/cli/commands/plan.ts
30999
+ import path45 from "node:path";
31000
+ function resolvePlanCommandOptions(command) {
31001
+ const localOptions = command.opts();
31002
+ const parentOptions = command.parent?.opts() ?? {};
31003
+ return {
31004
+ source: localOptions.source ?? parentOptions.source,
31005
+ output: localOptions.output ?? parentOptions.output
31006
+ };
31007
+ }
31008
+ function resolveOutputOption(value) {
31009
+ if (!value || value.trim().length === 0) {
31010
+ return "terminal";
31011
+ }
31012
+ const normalized = value.trim().toLowerCase();
31013
+ if (normalized === "json") {
31014
+ return "json";
31015
+ }
31016
+ if (normalized === "md" || normalized === "markdown") {
31017
+ return "markdown";
31018
+ }
31019
+ if (normalized === "terminal") {
31020
+ return "terminal";
31021
+ }
31022
+ throw new ValidationError(`Invalid --output value "${value}". Expected one of: terminal, md, json.`);
31023
+ }
31024
+ function resolveSource(value) {
31025
+ if (!value || value.trim().length === 0) {
31026
+ return void 0;
31027
+ }
31028
+ if (value === "pipeline" || value === "experiment" || value === "ralph") {
31029
+ return value;
31030
+ }
31031
+ throw new ValidationError(`Invalid --source value "${value}". Expected pipeline, experiment, or ralph.`);
31032
+ }
31033
+ function formatDate2(timestamp) {
31034
+ return new Date(timestamp).toISOString().slice(0, 10);
31035
+ }
31036
+ async function discoverPlans(container, source) {
31037
+ return discoverAllPlans({
31038
+ cwd: container.env.cwd,
31039
+ homeDir: container.env.homeDir,
31040
+ configPath: container.env.configPath,
31041
+ projectConfigPath: container.env.projectConfigPath,
31042
+ fs: container.fs,
31043
+ source,
31044
+ variables: container.env.variables
31045
+ });
31046
+ }
31047
+ async function resolveSelectedPlan(options) {
31048
+ const providedPath = options.providedPath?.trim();
31049
+ if (providedPath) {
31050
+ const resolvedAbsolute = providedPath.startsWith("~/") ? path45.join(options.container.env.homeDir, providedPath.slice(2)) : path45.isAbsolute(providedPath) ? providedPath : path45.resolve(options.container.env.cwd, providedPath);
31051
+ const matched2 = options.plans.find(
31052
+ (plan) => plan.path === providedPath || plan.absolutePath === providedPath || plan.absolutePath === resolvedAbsolute
31053
+ );
31054
+ if (!matched2) {
31055
+ throw new ValidationError(`Plan not found: ${providedPath}`);
31056
+ }
31057
+ return matched2;
31058
+ }
31059
+ if (options.plans.length === 0) {
31060
+ throw new ValidationError("No plans found.");
31061
+ }
31062
+ if (options.assumeYes) {
31063
+ return options.plans[0];
31064
+ }
31065
+ const selected = await select2({
31066
+ message: options.promptMessage,
31067
+ options: options.plans.map((plan) => ({
31068
+ label: text.selectLabel(path45.basename(plan.path), plan.status),
31069
+ hint: plan.source,
31070
+ value: plan.absolutePath
31071
+ }))
31072
+ });
31073
+ if (Ct(selected)) {
31074
+ throw new ValidationError("Plan selection cancelled.");
31075
+ }
31076
+ const matched = options.plans.find((plan) => plan.absolutePath === selected);
31077
+ if (!matched) {
31078
+ throw new ValidationError("Plan selection cancelled.");
31079
+ }
31080
+ return matched;
31081
+ }
31082
+ function writeOutput(format, value) {
31083
+ if (format === "terminal") {
31084
+ process.stdout.write(value.endsWith("\n") ? value : `${value}
31085
+ `);
31086
+ return;
31087
+ }
31088
+ const scopedFormat = format === "markdown" ? "markdown" : "json";
31089
+ withOutputFormat(scopedFormat, () => {
31090
+ process.stdout.write(value.endsWith("\n") ? value : `${value}
31091
+ `);
31092
+ });
31093
+ }
31094
+ async function renderPlanList(container, options) {
31095
+ const format = resolveOutputOption(options.output);
31096
+ const source = resolveSource(options.source);
31097
+ const plans = await discoverPlans(container, source);
31098
+ if (format === "json") {
31099
+ writeOutput(
31100
+ format,
31101
+ JSON.stringify(
31102
+ plans.map((plan) => ({
31103
+ source: plan.source,
31104
+ name: path45.basename(plan.path),
31105
+ path: plan.path,
31106
+ detail: plan.status,
31107
+ updated: formatDate2(plan.updatedAt)
31108
+ })),
31109
+ null,
31110
+ 2
31111
+ )
31112
+ );
31113
+ return;
31114
+ }
31115
+ const table = withOutputFormat(
31116
+ format,
31117
+ () => renderTable({
31118
+ theme: getTheme(),
31119
+ columns: [
31120
+ { name: "source", title: "Source", alignment: "left", maxLen: 12 },
31121
+ { name: "name", title: "Name", alignment: "left", maxLen: 32 },
31122
+ { name: "detail", title: "Detail", alignment: "left", maxLen: 40 },
31123
+ { name: "updated", title: "Updated", alignment: "left", maxLen: 12 }
31124
+ ],
31125
+ rows: plans.map((plan) => ({
31126
+ source: plan.source,
31127
+ name: path45.basename(plan.path),
31128
+ detail: plan.status,
31129
+ updated: formatDate2(plan.updatedAt)
31130
+ }))
31131
+ })
31132
+ );
31133
+ writeOutput(format, table);
31134
+ }
31135
+ async function executePlanAction(options) {
31136
+ intro(`plan ${options.action}`);
31137
+ const flags = resolveCommandFlags(options.program);
31138
+ const format = resolveOutputOption(options.output);
31139
+ const plans = await discoverPlans(options.container, resolveSource(options.source));
31140
+ const plan = await resolveSelectedPlan({
31141
+ container: options.container,
31142
+ plans,
31143
+ providedPath: options.pathArg,
31144
+ assumeYes: flags.assumeYes,
31145
+ promptMessage: `Select a plan to ${options.action}`
31146
+ });
31147
+ if (options.action === "edit") {
31148
+ editPlan(plan.absolutePath, {
31149
+ env: options.container.env.variables
31150
+ });
31151
+ writeOutput(
31152
+ format,
31153
+ format === "json" ? JSON.stringify({ action: "edit", path: plan.path }, null, 2) : `Edited ${plan.path}`
31154
+ );
31155
+ return;
31156
+ }
31157
+ if (!flags.assumeYes) {
31158
+ const confirmed = await confirmOrCancel({
31159
+ message: options.action === "archive" ? `Archive ${path45.basename(plan.path)}?` : `Permanently delete ${path45.basename(plan.path)}?`,
31160
+ initialValue: true
31161
+ });
31162
+ if (!confirmed) {
31163
+ return;
31164
+ }
31165
+ }
31166
+ if (options.action === "archive") {
31167
+ const archivedPath = await archivePlan3(
31168
+ plan,
31169
+ options.container.fs
31170
+ );
31171
+ writeOutput(
31172
+ format,
31173
+ format === "json" ? JSON.stringify({ action: "archive", path: plan.path, archivedPath }, null, 2) : `Archived ${plan.path}`
31174
+ );
31175
+ return;
31176
+ }
31177
+ await deletePlan(
31178
+ plan,
31179
+ options.container.fs
31180
+ );
31181
+ writeOutput(
31182
+ format,
31183
+ format === "json" ? JSON.stringify({ action: "delete", path: plan.path }, null, 2) : `Deleted ${plan.path}`
31184
+ );
31185
+ }
31186
+ function registerPlanCommand(program, container) {
31187
+ const plan = program.command("plan").description("Browse, view, and manage plans across pipeline, experiment, and Ralph.").option("--source <source>", "Filter by plan source: pipeline, experiment, or ralph").action(async function() {
31188
+ const opts = this.opts();
31189
+ const flags = resolveCommandFlags(this);
31190
+ intro("plan browser");
31191
+ await runPlanBrowser({
31192
+ cwd: container.env.cwd,
31193
+ homeDir: container.env.homeDir,
31194
+ configPath: container.env.configPath,
31195
+ projectConfigPath: container.env.projectConfigPath,
31196
+ fs: container.fs,
31197
+ source: resolveSource(opts.source),
31198
+ variables: container.env.variables,
31199
+ assumeYes: flags.assumeYes
31200
+ });
31201
+ });
31202
+ plan.command("list").description("List plans across all plan systems.").option("--source <source>", "Filter by plan source: pipeline, experiment, or ralph").option("--output <format>", "Output format: terminal, md, or json").action(async function() {
31203
+ intro("plan list");
31204
+ await renderPlanList(container, resolvePlanCommandOptions(this));
31205
+ });
31206
+ plan.command("view").description("Render a single plan to the terminal.").argument("[path]", "Plan path").option("--source <source>", "Filter by plan source: pipeline, experiment, or ralph").option("--output <format>", "Output format: terminal, md, or json").action(async function(pathArg) {
31207
+ intro("plan view");
31208
+ const flags = resolveCommandFlags(program);
31209
+ const options = resolvePlanCommandOptions(this);
31210
+ const format = resolveOutputOption(options.output);
31211
+ const plans = await discoverPlans(container, resolveSource(options.source));
31212
+ const plan2 = await resolveSelectedPlan({
31213
+ container,
31214
+ plans,
31215
+ providedPath: pathArg,
31216
+ assumeYes: flags.assumeYes,
31217
+ promptMessage: "Select a plan to view"
31218
+ });
31219
+ const markdown = await loadPlanPreviewMarkdown(plan2, container.fs);
31220
+ if (format === "json") {
31221
+ writeOutput(
31222
+ format,
31223
+ JSON.stringify(
31224
+ {
31225
+ source: plan2.source,
31226
+ path: plan2.path,
31227
+ title: plan2.title,
31228
+ detail: plan2.status,
31229
+ content: markdown
31230
+ },
31231
+ null,
31232
+ 2
31233
+ )
31234
+ );
31235
+ return;
31236
+ }
31237
+ const output = format === "markdown" ? markdown : renderMarkdown(markdown);
31238
+ writeOutput(format, output.trimEnd());
31239
+ });
31240
+ plan.command("edit").description("Open a plan in $EDITOR.").argument("[path]", "Plan path").option("--source <source>", "Filter by plan source: pipeline, experiment, or ralph").option("--output <format>", "Output format: terminal, md, or json").action(async function(pathArg) {
31241
+ await executePlanAction({
31242
+ program,
31243
+ container,
31244
+ action: "edit",
31245
+ pathArg,
31246
+ ...resolvePlanCommandOptions(this)
31247
+ });
31248
+ });
31249
+ plan.command("archive").description("Move a plan into archive/.").argument("[path]", "Plan path").option("--source <source>", "Filter by plan source: pipeline, experiment, or ralph").option("--output <format>", "Output format: terminal, md, or json").action(async function(pathArg) {
31250
+ await executePlanAction({
31251
+ program,
31252
+ container,
31253
+ action: "archive",
31254
+ pathArg,
31255
+ ...resolvePlanCommandOptions(this)
31256
+ });
31257
+ });
31258
+ plan.command("delete").description("Delete a plan file.").argument("[path]", "Plan path").option("--source <source>", "Filter by plan source: pipeline, experiment, or ralph").option("--output <format>", "Output format: terminal, md, or json").action(async function(pathArg) {
31259
+ await executePlanAction({
31260
+ program,
31261
+ container,
31262
+ action: "delete",
31263
+ pathArg,
31264
+ ...resolvePlanCommandOptions(this)
31265
+ });
31266
+ });
31267
+ }
31268
+ var init_plan = __esm({
31269
+ "src/cli/commands/plan.ts"() {
31270
+ "use strict";
31271
+ init_src5();
31272
+ init_src23();
31273
+ init_errors();
31274
+ init_shared();
31275
+ }
31276
+ });
31277
+
31278
+ // src/cli/commands/ralph.ts
31279
+ import path46 from "node:path";
30434
31280
  function formatDuration2(ms) {
30435
31281
  const totalSeconds = Math.round(ms / 1e3);
30436
31282
  const minutes = Math.floor(totalSeconds / 60);
@@ -30466,9 +31312,9 @@ function normalizeConfiguredIterations(value) {
30466
31312
  }
30467
31313
  function resolveAbsoluteDocPath4(container, docPath) {
30468
31314
  if (docPath.startsWith("~/")) {
30469
- return path41.join(container.env.homeDir, docPath.slice(2));
31315
+ return path46.join(container.env.homeDir, docPath.slice(2));
30470
31316
  }
30471
- return path41.isAbsolute(docPath) ? docPath : path41.resolve(container.env.cwd, docPath);
31317
+ return path46.isAbsolute(docPath) ? docPath : path46.resolve(container.env.cwd, docPath);
30472
31318
  }
30473
31319
  async function resolvePlanDirectory2(container) {
30474
31320
  const configDoc = await readMergedDocument(
@@ -30839,11 +31685,11 @@ var init_ralph3 = __esm({
30839
31685
  });
30840
31686
 
30841
31687
  // src/cli/commands/experiment.ts
30842
- import path42 from "node:path";
30843
- import { readFile as readFile15, stat as stat12 } from "node:fs/promises";
31688
+ import path47 from "node:path";
31689
+ import { readFile as readFile15, stat as stat13 } from "node:fs/promises";
30844
31690
  import { fileURLToPath as fileURLToPath8 } from "node:url";
30845
31691
  function resolveExperimentPaths(scope, cwd, homeDir) {
30846
- const rootPath = scope === "global" ? path42.join(homeDir, ".poe-code", "experiments") : path42.join(cwd, ".poe-code", "experiments");
31692
+ const rootPath = scope === "global" ? path47.join(homeDir, ".poe-code", "experiments") : path47.join(cwd, ".poe-code", "experiments");
30847
31693
  const displayRoot = scope === "global" ? "~/.poe-code/experiments" : ".poe-code/experiments";
30848
31694
  return {
30849
31695
  experimentsPath: rootPath,
@@ -30852,7 +31698,7 @@ function resolveExperimentPaths(scope, cwd, homeDir) {
30852
31698
  }
30853
31699
  async function pathExistsOnDisk2(targetPath) {
30854
31700
  try {
30855
- await stat12(targetPath);
31701
+ await stat13(targetPath);
30856
31702
  return true;
30857
31703
  } catch (error2) {
30858
31704
  if (error2 && typeof error2 === "object" && "code" in error2 && error2.code === "ENOENT") {
@@ -30862,12 +31708,12 @@ async function pathExistsOnDisk2(targetPath) {
30862
31708
  }
30863
31709
  }
30864
31710
  async function findPackageRoot2(entryFilePath) {
30865
- let currentPath = path42.dirname(entryFilePath);
31711
+ let currentPath = path47.dirname(entryFilePath);
30866
31712
  while (true) {
30867
- if (await pathExistsOnDisk2(path42.join(currentPath, "package.json"))) {
31713
+ if (await pathExistsOnDisk2(path47.join(currentPath, "package.json"))) {
30868
31714
  return currentPath;
30869
31715
  }
30870
- const parentPath = path42.dirname(currentPath);
31716
+ const parentPath = path47.dirname(currentPath);
30871
31717
  if (parentPath === currentPath) {
30872
31718
  throw new Error("Unable to locate package root for Experiment templates.");
30873
31719
  }
@@ -30880,16 +31726,16 @@ async function loadExperimentTemplates() {
30880
31726
  }
30881
31727
  const packageRoot = await findPackageRoot2(fileURLToPath8(import.meta.url));
30882
31728
  const templateRoots = [
30883
- path42.join(packageRoot, "src", "templates", "experiment"),
30884
- path42.join(packageRoot, "dist", "templates", "experiment")
31729
+ path47.join(packageRoot, "src", "templates", "experiment"),
31730
+ path47.join(packageRoot, "dist", "templates", "experiment")
30885
31731
  ];
30886
31732
  for (const templateRoot of templateRoots) {
30887
31733
  if (!await pathExistsOnDisk2(templateRoot)) {
30888
31734
  continue;
30889
31735
  }
30890
31736
  const [skillPlan, runYaml] = await Promise.all([
30891
- readFile15(path42.join(templateRoot, "SKILL_experiment.md"), "utf8"),
30892
- readFile15(path42.join(templateRoot, "run.yaml.hbs"), "utf8")
31737
+ readFile15(path47.join(templateRoot, "SKILL_experiment.md"), "utf8"),
31738
+ readFile15(path47.join(templateRoot, "run.yaml.hbs"), "utf8")
30893
31739
  ]);
30894
31740
  experimentTemplatesCache = { skillPlan, runYaml };
30895
31741
  return experimentTemplatesCache;
@@ -30976,15 +31822,15 @@ async function resolveExperimentPlanDirectory(container) {
30976
31822
  }
30977
31823
  function resolveAbsoluteDocPath5(container, docPath) {
30978
31824
  if (docPath.startsWith("~/")) {
30979
- return path42.join(container.env.homeDir, docPath.slice(2));
31825
+ return path47.join(container.env.homeDir, docPath.slice(2));
30980
31826
  }
30981
- return path42.isAbsolute(docPath) ? docPath : path42.resolve(container.env.cwd, docPath);
31827
+ return path47.isAbsolute(docPath) ? docPath : path47.resolve(container.env.cwd, docPath);
30982
31828
  }
30983
- function resolveAbsoluteDirectory3(dir, cwd, homeDir) {
31829
+ function resolveAbsoluteDirectory4(dir, cwd, homeDir) {
30984
31830
  if (dir.startsWith("~/")) {
30985
- return path42.join(homeDir, dir.slice(2));
31831
+ return path47.join(homeDir, dir.slice(2));
30986
31832
  }
30987
- return path42.isAbsolute(dir) ? dir : path42.resolve(cwd, dir);
31833
+ return path47.isAbsolute(dir) ? dir : path47.resolve(cwd, dir);
30988
31834
  }
30989
31835
  async function scanExperimentDir(container, absoluteDir, displayDir) {
30990
31836
  let names;
@@ -31001,12 +31847,12 @@ async function scanExperimentDir(container, absoluteDir, displayDir) {
31001
31847
  if (!name.endsWith(".md")) {
31002
31848
  continue;
31003
31849
  }
31004
- const absolutePath = path42.join(absoluteDir, name);
31850
+ const absolutePath = path47.join(absoluteDir, name);
31005
31851
  const fileStat = await container.fs.stat(absolutePath);
31006
31852
  if (!fileStat.isFile()) {
31007
31853
  continue;
31008
31854
  }
31009
- const displayPath = path42.join(displayDir, name);
31855
+ const displayPath = path47.join(displayDir, name);
31010
31856
  docs.push({ path: displayPath, displayPath });
31011
31857
  }
31012
31858
  return docs;
@@ -31014,12 +31860,12 @@ async function scanExperimentDir(container, absoluteDir, displayDir) {
31014
31860
  async function discoverExperimentDocs(container, planDirectory) {
31015
31861
  const customDir = planDirectory?.trim();
31016
31862
  if (customDir) {
31017
- const absoluteDir = resolveAbsoluteDirectory3(customDir, container.env.cwd, container.env.homeDir);
31863
+ const absoluteDir = resolveAbsoluteDirectory4(customDir, container.env.cwd, container.env.homeDir);
31018
31864
  return scanExperimentDir(container, absoluteDir, customDir);
31019
31865
  }
31020
31866
  return scanExperimentDir(
31021
31867
  container,
31022
- path42.join(container.env.cwd, EXPERIMENTS_DIRECTORY),
31868
+ path47.join(container.env.cwd, EXPERIMENTS_DIRECTORY),
31023
31869
  EXPERIMENTS_DIRECTORY
31024
31870
  );
31025
31871
  }
@@ -31396,12 +32242,12 @@ function registerExperimentCommand(program, container) {
31396
32242
  scope = selected;
31397
32243
  }
31398
32244
  resources.logger.intro(`experiment install (${support.id}, ${scope})`);
31399
- const templates = await loadExperimentTemplates();
32245
+ const templates2 = await loadExperimentTemplates();
31400
32246
  const skillResult = await installSkill(
31401
32247
  support.id,
31402
32248
  {
31403
32249
  name: "poe-code-experiment-plan",
31404
- content: templates.skillPlan
32250
+ content: templates2.skillPlan
31405
32251
  },
31406
32252
  {
31407
32253
  fs: container.fs,
@@ -31435,13 +32281,13 @@ function registerExperimentCommand(program, container) {
31435
32281
  );
31436
32282
  }
31437
32283
  }
31438
- const runYamlPath = path42.join(experimentPaths.experimentsPath, "run.yaml");
31439
- const runYamlDisplayPath = path42.join(experimentPaths.displayExperimentsPath, "run.yaml");
32284
+ const runYamlPath = path47.join(experimentPaths.experimentsPath, "run.yaml");
32285
+ const runYamlDisplayPath = path47.join(experimentPaths.displayExperimentsPath, "run.yaml");
31440
32286
  if (!await pathExists4(container.fs, runYamlPath)) {
31441
32287
  if (flags.dryRun) {
31442
32288
  resources.logger.dryRun(`Would create: ${runYamlDisplayPath}`);
31443
32289
  } else {
31444
- await container.fs.writeFile(runYamlPath, templates.runYaml);
32290
+ await container.fs.writeFile(runYamlPath, templates2.runYaml);
31445
32291
  resources.logger.info(`Create: ${runYamlDisplayPath}`);
31446
32292
  }
31447
32293
  }
@@ -31470,7 +32316,7 @@ var init_experiment2 = __esm({
31470
32316
  init_src4();
31471
32317
  DEFAULT_EXPERIMENT_AGENT = "claude-code";
31472
32318
  DEFAULT_EXPERIMENT_SCOPE = "local";
31473
- EXPERIMENTS_DIRECTORY = path42.join(".poe-code", "experiments");
32319
+ EXPERIMENTS_DIRECTORY = path47.join(".poe-code", "experiments");
31474
32320
  experimentTemplatesCache = null;
31475
32321
  }
31476
32322
  });
@@ -31902,7 +32748,7 @@ var init_package = __esm({
31902
32748
  "package.json"() {
31903
32749
  package_default = {
31904
32750
  name: "poe-code",
31905
- version: "3.0.155",
32751
+ version: "3.0.156",
31906
32752
  description: "CLI tool to configure Poe API for developer workflows.",
31907
32753
  type: "module",
31908
32754
  main: "./dist/index.js",
@@ -32010,6 +32856,7 @@ var init_package = __esm({
32010
32856
  "@poe-code/e2e-docker-test-runner": "*",
32011
32857
  "@poe-code/experiment-loop": "*",
32012
32858
  "@poe-code/github-workflows": "*",
32859
+ "@poe-code/plan-browser": "*",
32013
32860
  "@poe-code/pipeline": "*",
32014
32861
  "@poe-code/poe-acp-client": "*",
32015
32862
  "@poe-code/poe-agent": "*",
@@ -32077,22 +32924,22 @@ function formatCommandHeader(cmd) {
32077
32924
  }
32078
32925
  return `Poe - ${parts.reverse().join(" ")}`;
32079
32926
  }
32080
- function findCommandByPath(root, path43) {
32927
+ function findCommandByPath(root, path48) {
32081
32928
  let current = root;
32082
- for (const segment of path43) {
32929
+ for (const segment of path48) {
32083
32930
  const next = current.commands.find(
32084
32931
  (command) => Reflect.get(command, "_hidden") !== true && command.name() === segment
32085
32932
  );
32086
32933
  if (!next) {
32087
- throw new Error(`Root help command is missing: ${path43.join(" ")}`);
32934
+ throw new Error(`Root help command is missing: ${path48.join(" ")}`);
32088
32935
  }
32089
32936
  current = next;
32090
32937
  }
32091
32938
  return current;
32092
32939
  }
32093
- function formatRootHelpCommandName(path43, command) {
32940
+ function formatRootHelpCommandName(path48, command) {
32094
32941
  const leaf = [command.name(), ...command.aliases()].join(", ");
32095
- return path43.length > 1 ? [...path43.slice(0, -1), leaf].join(" ") : leaf;
32942
+ return path48.length > 1 ? [...path48.slice(0, -1), leaf].join(" ") : leaf;
32096
32943
  }
32097
32944
  function splitUsageParts(usage) {
32098
32945
  return usage.split(" ").map((part) => part.trim()).filter((part) => part.length > 0);
@@ -32309,6 +33156,7 @@ function bootstrapProgram(container) {
32309
33156
  registerMcpCommand(program, container);
32310
33157
  registerSkillCommand(program, container);
32311
33158
  registerPipelineCommand(program, container);
33159
+ registerPlanCommand(program, container);
32312
33160
  registerRalphCommand(program, container);
32313
33161
  registerExperimentCommand(program, container);
32314
33162
  registerLaunchCommand(program, container);
@@ -32381,6 +33229,7 @@ var init_program = __esm({
32381
33229
  init_usage();
32382
33230
  init_models2();
32383
33231
  await init_pipeline3();
33232
+ init_plan();
32384
33233
  await init_ralph3();
32385
33234
  await init_experiment2();
32386
33235
  init_launch2();
@@ -32407,6 +33256,7 @@ var init_program = __esm({
32407
33256
  { path: ["pipeline", "install"] },
32408
33257
  { path: ["pipeline", "run"] },
32409
33258
  { path: ["pipeline", "validate"] },
33259
+ { path: ["plan"] },
32410
33260
  { path: ["experiment", "install"] },
32411
33261
  { path: ["experiment", "run"] },
32412
33262
  { path: ["experiment", "journal"] },