poe-code 4.0.49 → 4.0.51

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
@@ -76430,7 +76430,7 @@ function toPlanKind(value, filePath) {
76430
76430
  }
76431
76431
  throw new Error(`${filePath}: unsupported frontmatter kind ${JSON.stringify(value)}`);
76432
76432
  }
76433
- function classifyPlanKind(content, filePath) {
76433
+ function classifyPlanKind(content, filePath, archived = false) {
76434
76434
  if (isYamlPlanFile(filePath)) {
76435
76435
  parsePlan(content);
76436
76436
  return "pipeline";
@@ -76439,13 +76439,24 @@ function classifyPlanKind(content, filePath) {
76439
76439
  if (data === void 0) {
76440
76440
  return "plan";
76441
76441
  }
76442
- return data.kind === void 0 ? "plan" : toPlanKind(data.kind, filePath);
76442
+ if (data.kind === void 0) return "plan";
76443
+ if (archived && data.kind === "archived-pipeline-plan") return "plan";
76444
+ if (archived) {
76445
+ try {
76446
+ return toPlanKind(data.kind, filePath);
76447
+ } catch {
76448
+ return "plan";
76449
+ }
76450
+ }
76451
+ return toPlanKind(data.kind, filePath);
76443
76452
  }
76444
76453
  function readPlanReadiness(content, filePath) {
76445
76454
  const value = splitFrontmatter2(content, filePath).data?.readiness;
76446
76455
  if (value === void 0 || value === "draft") return "draft";
76447
76456
  if (value === "ready") return value;
76448
- throw new Error(`${filePath}: invalid readiness ${JSON.stringify(value)}; expected "draft" or "ready"`);
76457
+ throw new Error(
76458
+ `${filePath}: invalid readiness ${JSON.stringify(value)}; expected "draft" or "ready"`
76459
+ );
76449
76460
  }
76450
76461
  async function discoverSharedPlans(options) {
76451
76462
  const displayDir = await resolveSharedPlanDirectory(options);
@@ -76462,6 +76473,14 @@ async function discoverSharedPlans(options) {
76462
76473
  if (canonicalDir !== path89.resolve(absoluteDir)) {
76463
76474
  throw new Error(`Plan directory must not be a symbolic link: ${displayDir}`);
76464
76475
  }
76476
+ if (options.archived === true) {
76477
+ return discoverPlanDirectoryEntries({
76478
+ ...options,
76479
+ absoluteDir: path89.join(absoluteDir, "archive"),
76480
+ displayDir: path89.join(displayDir, "archive"),
76481
+ savedForLaterDirectory: false
76482
+ });
76483
+ }
76465
76484
  const activePlans = await discoverPlanDirectoryEntries({
76466
76485
  ...options,
76467
76486
  absoluteDir,
@@ -76502,7 +76521,9 @@ async function discoverPlanDirectoryEntries(options) {
76502
76521
  continue;
76503
76522
  }
76504
76523
  if (canonicalPath !== path89.resolve(absolutePath)) {
76505
- throw new Error(`Plan file must not be a symbolic link: ${path89.join(options.displayDir, name)}`);
76524
+ throw new Error(
76525
+ `Plan file must not be a symbolic link: ${path89.join(options.displayDir, name)}`
76526
+ );
76506
76527
  }
76507
76528
  const stat36 = await options.fs.stat(absolutePath).catch((error3) => {
76508
76529
  if (isNotFound4(error3)) {
@@ -76518,18 +76539,31 @@ async function discoverPlanDirectoryEntries(options) {
76518
76539
  }
76519
76540
  const displayPath = path89.join(options.displayDir, name);
76520
76541
  const content = await options.fs.readFile(absolutePath, "utf8");
76521
- const kind = classifyPlanKind(content, displayPath);
76542
+ let kind = classifyPlanKind(content, displayPath, options.archived);
76543
+ const savedForLater = options.savedForLaterDirectory ? readSavedForLaterMetadata(content, displayPath) ?? {} : readSavedForLaterMetadata(content, displayPath);
76544
+ let metadata;
76545
+ try {
76546
+ metadata = await readPlanMetadata({
76547
+ kind,
76548
+ absolutePath,
76549
+ path: displayPath,
76550
+ fs: options.fs,
76551
+ content
76552
+ });
76553
+ } catch (error3) {
76554
+ if (!options.archived || kind === "plan") throw error3;
76555
+ kind = "plan";
76556
+ metadata = await readPlanMetadata({
76557
+ kind,
76558
+ absolutePath,
76559
+ path: displayPath,
76560
+ fs: options.fs,
76561
+ content
76562
+ });
76563
+ }
76522
76564
  if (options.kind && kind !== options.kind) {
76523
76565
  continue;
76524
76566
  }
76525
- const savedForLater = options.savedForLaterDirectory ? readSavedForLaterMetadata(content, displayPath) ?? {} : readSavedForLaterMetadata(content, displayPath);
76526
- const metadata = await readPlanMetadata({
76527
- kind,
76528
- absolutePath,
76529
- path: displayPath,
76530
- fs: options.fs,
76531
- content
76532
- });
76533
76567
  plans.push({
76534
76568
  path: displayPath,
76535
76569
  absolutePath,
@@ -76668,6 +76702,25 @@ async function archiveSelectedPlan(entry, fs31) {
76668
76702
  }
76669
76703
  return archivedPath;
76670
76704
  }
76705
+ async function unarchivePlan(entry, fs31) {
76706
+ rejectPlanMetaDocument(entry.absolutePath, "unarchive");
76707
+ const archiveDir = path90.dirname(entry.absolutePath);
76708
+ if (path90.basename(archiveDir) !== "archive") {
76709
+ throw new Error(`Plan is not archived: ${entry.absolutePath}`);
76710
+ }
76711
+ await rejectSymbolicLink2(archiveDir, fs31, "unarchive plan through");
76712
+ const destinationPath = path90.join(path90.dirname(archiveDir), path90.basename(entry.absolutePath));
76713
+ try {
76714
+ await fs31.readFile(destinationPath, "utf8");
76715
+ throw new Error(`Unarchive destination already exists: ${destinationPath}`);
76716
+ } catch (error3) {
76717
+ if (!hasErrorCode3(error3, "ENOENT")) {
76718
+ throw error3;
76719
+ }
76720
+ }
76721
+ await fs31.rename(entry.absolutePath, destinationPath);
76722
+ return destinationPath;
76723
+ }
76671
76724
  async function savePlanForLater(entry, fs31, options = {}) {
76672
76725
  const reason = entry.savedForLater?.reason?.trim() || options.reason?.trim();
76673
76726
  if (!reason) {
@@ -76813,14 +76866,14 @@ function buildPlanExplorerConfig(options) {
76813
76866
  const loadDetailMarkdown = options.loadDetailMarkdown ?? loadPlanPreviewMarkdown;
76814
76867
  const promptSaveReason = options.promptSaveReason;
76815
76868
  let plans = options.plans;
76816
- let rows = toRows(plans);
76869
+ let rows = toRows(plans, options.archived);
76817
76870
  let entryByRowId = toEntryMap(plans);
76818
76871
  let preserveOrderOnNextRefresh = false;
76819
76872
  async function refresh() {
76820
76873
  const refreshedPlans = await options.onRefresh();
76821
76874
  plans = preserveOrderOnNextRefresh ? preservePlanOrder(plans, refreshedPlans) : refreshedPlans;
76822
76875
  preserveOrderOnNextRefresh = false;
76823
- rows = toRows(plans);
76876
+ rows = toRows(plans, options.archived);
76824
76877
  entryByRowId = toEntryMap(plans);
76825
76878
  }
76826
76879
  const actions = [
@@ -76908,6 +76961,21 @@ function buildPlanExplorerConfig(options) {
76908
76961
  }
76909
76962
  }
76910
76963
  },
76964
+ {
76965
+ id: "unarchive",
76966
+ accelerator: "a",
76967
+ label: "Unarchive",
76968
+ handler: async (ctx) => {
76969
+ const entry = getEntry(entryByRowId, ctx.row.id);
76970
+ await unarchivePlan(entry, options.fs);
76971
+ try {
76972
+ await ctx.refresh();
76973
+ ctx.toast(`Unarchived ${path91.basename(entry.path)}`, "info");
76974
+ } catch {
76975
+ ctx.toast(`Unarchived ${path91.basename(entry.path)}; refresh failed`, "info");
76976
+ }
76977
+ }
76978
+ },
76911
76979
  {
76912
76980
  id: "delete",
76913
76981
  accelerator: "x",
@@ -76953,43 +77021,47 @@ function buildPlanExplorerConfig(options) {
76953
77021
  }
76954
77022
  ],
76955
77023
  refresh,
76956
- actions,
76957
- reorder: {
76958
- onReorder: async (orderedIds, ctx) => {
76959
- if (ctx === void 0) {
76960
- throw new Error("Plan reorder context is required");
76961
- }
76962
- const orderedEntries = orderedIds.map((id) => getEntry(entryByRowId, id));
76963
- const movedIndex = orderedIds.indexOf(ctx.movedId);
76964
- const originalIndex = createRowIds(plans).indexOf(ctx.movedId);
76965
- if (movedIndex < 0 || originalIndex < 0) {
76966
- throw new Error(`Plan row is no longer available: ${ctx.movedId}`);
76967
- }
76968
- const moved = orderedEntries[movedIndex];
76969
- const swapTarget = orderedEntries[originalIndex];
76970
- if (swapTarget === void 0 || swapTarget.readiness !== moved.readiness) {
76971
- throw new Error("Plans can only be reordered within the same readiness group");
76972
- }
76973
- if (isSavedForLaterEntry(swapTarget) !== isSavedForLaterEntry(moved)) {
76974
- throw new Error("Active and saved-for-later plans cannot be reordered together");
76975
- }
76976
- const previousCandidate = orderedEntries[movedIndex - 1];
76977
- const nextCandidate = orderedEntries[movedIndex + 1];
76978
- const previous = sameOrderingGroup(previousCandidate, moved) ? previousCandidate : void 0;
76979
- const next = sameOrderingGroup(nextCandidate, moved) ? nextCandidate : void 0;
76980
- const [movedStat, previousStat, nextStat] = await Promise.all([
76981
- options.fs.stat(moved.absolutePath),
76982
- previous === void 0 ? void 0 : options.fs.stat(previous.absolutePath),
76983
- next === void 0 ? void 0 : options.fs.stat(next.absolutePath)
76984
- ]);
76985
- const updatedAt = resolveMovedTimestamp(previousStat?.mtimeMs, nextStat?.mtimeMs);
76986
- await options.fs.utimes(
76987
- moved.absolutePath,
76988
- new Date(movedStat.atimeMs ?? movedStat.mtimeMs),
76989
- new Date(updatedAt)
76990
- );
76991
- await ctx.refresh();
76992
- ctx.toast(`Reordered ${path91.basename(moved.path)}`, "info");
77024
+ actions: options.archived ? actions.filter(
77025
+ (action) => action.id === "edit" || action.id === "unarchive" || action.id === "delete"
77026
+ ) : actions.filter((action) => action.id !== "unarchive"),
77027
+ ...options.archived ? {} : {
77028
+ reorder: {
77029
+ onReorder: async (orderedIds, ctx) => {
77030
+ if (ctx === void 0) {
77031
+ throw new Error("Plan reorder context is required");
77032
+ }
77033
+ const orderedEntries = orderedIds.map((id) => getEntry(entryByRowId, id));
77034
+ const movedIndex = orderedIds.indexOf(ctx.movedId);
77035
+ const originalIndex = createRowIds(plans).indexOf(ctx.movedId);
77036
+ if (movedIndex < 0 || originalIndex < 0) {
77037
+ throw new Error(`Plan row is no longer available: ${ctx.movedId}`);
77038
+ }
77039
+ const moved = orderedEntries[movedIndex];
77040
+ const swapTarget = orderedEntries[originalIndex];
77041
+ if (swapTarget === void 0 || swapTarget.readiness !== moved.readiness) {
77042
+ throw new Error("Plans can only be reordered within the same readiness group");
77043
+ }
77044
+ if (isSavedForLaterEntry(swapTarget) !== isSavedForLaterEntry(moved)) {
77045
+ throw new Error("Active and saved-for-later plans cannot be reordered together");
77046
+ }
77047
+ const previousCandidate = orderedEntries[movedIndex - 1];
77048
+ const nextCandidate = orderedEntries[movedIndex + 1];
77049
+ const previous = sameOrderingGroup(previousCandidate, moved) ? previousCandidate : void 0;
77050
+ const next = sameOrderingGroup(nextCandidate, moved) ? nextCandidate : void 0;
77051
+ const [movedStat, previousStat, nextStat] = await Promise.all([
77052
+ options.fs.stat(moved.absolutePath),
77053
+ previous === void 0 ? void 0 : options.fs.stat(previous.absolutePath),
77054
+ next === void 0 ? void 0 : options.fs.stat(next.absolutePath)
77055
+ ]);
77056
+ const updatedAt = resolveMovedTimestamp(previousStat?.mtimeMs, nextStat?.mtimeMs);
77057
+ await options.fs.utimes(
77058
+ moved.absolutePath,
77059
+ new Date(movedStat.atimeMs ?? movedStat.mtimeMs),
77060
+ new Date(updatedAt)
77061
+ );
77062
+ await ctx.refresh();
77063
+ ctx.toast(`Reordered ${path91.basename(moved.path)}`, "info");
77064
+ }
76993
77065
  }
76994
77066
  },
76995
77067
  multiSelect: false,
@@ -77034,14 +77106,14 @@ function abbreviateHome(filePath, homeDir) {
77034
77106
  }
77035
77107
  return `~${path91.sep}${relative8}`;
77036
77108
  }
77037
- function toRows(plans) {
77109
+ function toRows(plans, archived = false) {
77038
77110
  const rowIds = createRowIds(plans);
77039
77111
  return plans.map((entry, index) => ({
77040
77112
  id: rowIds[index],
77041
77113
  title: formatPlanReadinessLabel(path91.basename(entry.path), entry.readiness),
77042
77114
  subtitle: formatSubtitle(entry),
77043
77115
  badge: { text: entry.typeLabel },
77044
- group: isSavedForLaterEntry(entry) ? "Saved for later" : "Active"
77116
+ group: archived ? "Archived" : isSavedForLaterEntry(entry) ? "Saved for later" : "Active"
77045
77117
  }));
77046
77118
  }
77047
77119
  function formatSubtitle(entry) {
@@ -77109,6 +77181,7 @@ async function runPlanBrowser(options) {
77109
77181
  projectConfigPath: options.projectConfigPath,
77110
77182
  fs: options.fs,
77111
77183
  kind: options.kind,
77184
+ archived: options.archived,
77112
77185
  variables: options.variables
77113
77186
  });
77114
77187
  const plans = await discover();
@@ -77128,6 +77201,7 @@ async function runPlanBrowser(options) {
77128
77201
  }
77129
77202
  const config2 = buildPlanExplorerConfig({
77130
77203
  plans,
77204
+ archived: options.archived,
77131
77205
  fs: options.fs,
77132
77206
  variables: options.variables ?? process.env,
77133
77207
  homeDir: options.homeDir,
@@ -77840,7 +77914,8 @@ function resolvePlanCommandOptions(command) {
77840
77914
  const parentOptions = command.parent?.opts() ?? {};
77841
77915
  return {
77842
77916
  kind: localOptions.kind ?? parentOptions.kind,
77843
- output: localOptions.output ?? parentOptions.output
77917
+ output: localOptions.output ?? parentOptions.output,
77918
+ archived: localOptions.archived ?? parentOptions.archived
77844
77919
  };
77845
77920
  }
77846
77921
  function resolveOutputOption(value) {
@@ -77870,7 +77945,7 @@ function resolveKind(value) {
77870
77945
  }
77871
77946
  throw new ValidationError(`Invalid --kind value "${value}". Expected ${VALID_KINDS.join(", ")}.`);
77872
77947
  }
77873
- function createPlanBrowserOptions(container, kind) {
77948
+ function createPlanBrowserOptions(container, kind, archived = false) {
77874
77949
  return {
77875
77950
  cwd: container.env.cwd,
77876
77951
  homeDir: container.env.homeDir,
@@ -77878,6 +77953,7 @@ function createPlanBrowserOptions(container, kind) {
77878
77953
  projectConfigPath: container.env.projectConfigPath,
77879
77954
  fs: container.fs,
77880
77955
  kind,
77956
+ archived,
77881
77957
  variables: container.env.variables
77882
77958
  };
77883
77959
  }
@@ -77972,7 +78048,7 @@ function formatMarkdownReadSectionOutput(result, format) {
77972
78048
  }
77973
78049
  return result.markdown.trimEnd();
77974
78050
  }
77975
- async function discoverPlans2(container, kind) {
78051
+ async function discoverPlans2(container, kind, archived = false) {
77976
78052
  return discoverAllPlans({
77977
78053
  cwd: container.env.cwd,
77978
78054
  homeDir: container.env.homeDir,
@@ -77980,6 +78056,7 @@ async function discoverPlans2(container, kind) {
77980
78056
  projectConfigPath: container.env.projectConfigPath,
77981
78057
  fs: container.fs,
77982
78058
  kind,
78059
+ archived,
77983
78060
  variables: container.env.variables
77984
78061
  });
77985
78062
  }
@@ -77987,7 +78064,7 @@ async function requirePlanBrowsingPrompt(options) {
77987
78064
  if (!options.assumeYes && process.stdin.isTTY === true) {
77988
78065
  return;
77989
78066
  }
77990
- const plans = await discoverPlans2(options.container, options.kind);
78067
+ const plans = await discoverPlans2(options.container, options.kind, options.archived);
77991
78068
  if (plans.length === 0) {
77992
78069
  return;
77993
78070
  }
@@ -78116,7 +78193,11 @@ async function executePlanAction(options) {
78116
78193
  if (format === "terminal") {
78117
78194
  intro(`plan ${options.action}`);
78118
78195
  }
78119
- const plans = await discoverPlans2(options.container, resolveKind(options.kind));
78196
+ const plans = await discoverPlans2(
78197
+ options.container,
78198
+ resolveKind(options.kind),
78199
+ options.action === "unarchive"
78200
+ );
78120
78201
  const plan = await resolveSelectedPlan({
78121
78202
  container: options.container,
78122
78203
  plans,
@@ -78169,7 +78250,7 @@ async function executePlanAction(options) {
78169
78250
  `plan ${options.action} requires --yes when running without an interactive TTY.`
78170
78251
  );
78171
78252
  const confirmed = await confirmOrCancel({
78172
- message: options.action === "archive" ? `Archive ${path93.basename(plan.path)}?` : `Permanently delete ${path93.basename(plan.path)}?`,
78253
+ message: options.action === "archive" ? `Archive ${path93.basename(plan.path)}?` : options.action === "unarchive" ? `Unarchive ${path93.basename(plan.path)}?` : `Permanently delete ${path93.basename(plan.path)}?`,
78173
78254
  initialValue: false
78174
78255
  });
78175
78256
  if (!confirmed) {
@@ -78187,6 +78268,17 @@ async function executePlanAction(options) {
78187
78268
  );
78188
78269
  return;
78189
78270
  }
78271
+ if (options.action === "unarchive") {
78272
+ const restoredPath = await unarchivePlan(
78273
+ plan,
78274
+ options.container.fs
78275
+ );
78276
+ writeOutput(
78277
+ format,
78278
+ format === "json" ? JSON.stringify({ action: "unarchive", path: plan.path, restoredPath }, null, 2) : `Unarchived ${plan.path}`
78279
+ );
78280
+ return;
78281
+ }
78190
78282
  await deletePlan(plan, options.container.fs);
78191
78283
  writeOutput(
78192
78284
  format,
@@ -78197,7 +78289,7 @@ function registerPlanCommand(program, container) {
78197
78289
  const plan = program.command("plan").alias("plans").description("Browse and manage plans.").usage("[options] [command]").allowExcessArguments().option(
78198
78290
  "--kind <kind>",
78199
78291
  "Filter by plan kind: plan, pipeline, experiment, ralph, superintendent, or superintendent-base"
78200
- ).action(async function() {
78292
+ ).option("--archived", "Browse archived plans instead of active plans").action(async function() {
78201
78293
  if (this.args.length > 0) {
78202
78294
  const candidates = plan.commands.flatMap((command) => [
78203
78295
  command.name(),
@@ -78215,19 +78307,24 @@ function registerPlanCommand(program, container) {
78215
78307
  const opts = this.opts();
78216
78308
  const flags = resolveCommandFlags(program);
78217
78309
  const kind = resolveKind(opts.kind);
78218
- await requirePlanBrowsingPrompt({ container, kind, assumeYes: flags.assumeYes });
78310
+ await requirePlanBrowsingPrompt({
78311
+ container,
78312
+ kind,
78313
+ assumeYes: flags.assumeYes,
78314
+ archived: opts.archived
78315
+ });
78219
78316
  intro("plan");
78220
- await runPlanBrowser(createPlanBrowserOptions(container, kind));
78317
+ await runPlanBrowser(createPlanBrowserOptions(container, kind, opts.archived));
78221
78318
  });
78222
78319
  plan.command("browse").description("Browse plans in the interactive explorer, or render one plan when given a path.").argument("[path]", "Plan path to render instead of opening the explorer").option(
78223
78320
  "--kind <kind>",
78224
78321
  "Filter by plan kind: plan, pipeline, experiment, ralph, superintendent, or superintendent-base"
78225
- ).action(async function(pathArg) {
78322
+ ).option("--archived", "Browse archived plans instead of active plans").action(async function(pathArg) {
78226
78323
  const opts = resolvePlanCommandOptions(this);
78227
78324
  const flags = resolveCommandFlags(program);
78228
78325
  const kind = resolveKind(opts.kind);
78229
78326
  if ((pathArg?.trim() ?? "").length > 0) {
78230
- const plans = await discoverPlans2(container, kind);
78327
+ const plans = await discoverPlans2(container, kind, opts.archived);
78231
78328
  const selected = await resolveSelectedPlan({
78232
78329
  container,
78233
78330
  plans,
@@ -78239,9 +78336,14 @@ function registerPlanCommand(program, container) {
78239
78336
  writeOutput("terminal", renderMarkdown(markdown).trimEnd());
78240
78337
  return;
78241
78338
  }
78242
- await requirePlanBrowsingPrompt({ container, kind, assumeYes: flags.assumeYes });
78339
+ await requirePlanBrowsingPrompt({
78340
+ container,
78341
+ kind,
78342
+ assumeYes: flags.assumeYes,
78343
+ archived: opts.archived
78344
+ });
78243
78345
  intro("plan browser");
78244
- await runPlanBrowser(createPlanBrowserOptions(container, kind));
78346
+ await runPlanBrowser(createPlanBrowserOptions(container, kind, opts.archived));
78245
78347
  });
78246
78348
  plan.command("list").description("List plans across all plan systems.").option(
78247
78349
  "--kind <kind>",
@@ -78365,6 +78467,18 @@ function registerPlanCommand(program, container) {
78365
78467
  ...resolvePlanCommandOptions(this)
78366
78468
  });
78367
78469
  });
78470
+ plan.command("unarchive").description("Move an archived plan back into the active plan directory.").argument("[path]", "Archived plan path").option(
78471
+ "--kind <kind>",
78472
+ "Filter by plan kind: plan, pipeline, experiment, ralph, superintendent, or superintendent-base"
78473
+ ).option("--output <format>", "Output format: terminal, md, or json").action(async function(pathArg) {
78474
+ await executePlanAction({
78475
+ program,
78476
+ container,
78477
+ action: "unarchive",
78478
+ pathArg,
78479
+ ...resolvePlanCommandOptions(this)
78480
+ });
78481
+ });
78368
78482
  plan.command("delete").description("Delete a plan file.").argument("[path]", "Plan path").option(
78369
78483
  "--kind <kind>",
78370
78484
  "Filter by plan kind: plan, pipeline, experiment, ralph, superintendent, or superintendent-base"
@@ -152722,7 +152836,7 @@ var init_package2 = __esm({
152722
152836
  "package.json"() {
152723
152837
  package_default2 = {
152724
152838
  name: "poe-code",
152725
- version: "4.0.49",
152839
+ version: "4.0.51",
152726
152840
  description: "CLI tool to configure Poe API for developer workflows.",
152727
152841
  license: "MIT",
152728
152842
  type: "module",