akm-cli 0.9.25-alpha.2 → 0.9.25-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51767,6 +51767,170 @@ var codexResultExtractor = (result) => {
51767
51767
  return sessionId === undefined ? { text } : { text, sessionId };
51768
51768
  };
51769
51769
 
51770
+ // src/integrations/harnesses/codex/session-log.ts
51771
+ import fs36 from "node:fs";
51772
+ import os5 from "node:os";
51773
+ import path43 from "node:path";
51774
+ function codexSessionsDir() {
51775
+ return path43.join(process.env.CODEX_HOME || path43.join(os5.homedir(), ".codex"), "sessions");
51776
+ }
51777
+ var META_PEEK_BYTES = 128 * 1024;
51778
+ var INJECTED_CONTEXT_RE = /^\s*(?:# AGENTS\.md instructions[\s\S]*<\/INSTRUCTIONS>|<(environment_context|user_instructions|recommended_plugins|skill|turn_aborted)>[\s\S]*<\/\1>)\s*$/i;
51779
+ function parseSessionMeta(entry) {
51780
+ const e = entry;
51781
+ if (e?.type !== "session_meta" || !e.payload)
51782
+ return;
51783
+ const { timestamp, cwd, source } = e.payload;
51784
+ const startedAt = typeof timestamp === "string" ? Date.parse(timestamp) : Number.NaN;
51785
+ return {
51786
+ ...Number.isNaN(startedAt) ? {} : { startedAt },
51787
+ ...typeof cwd === "string" ? { cwd } : {},
51788
+ isAgent: typeof source === "object" && source !== null && (("subagent" in source) || ("internal" in source))
51789
+ };
51790
+ }
51791
+ function blockText(blocks, keep = () => true) {
51792
+ if (typeof blocks === "string")
51793
+ return blocks;
51794
+ if (!Array.isArray(blocks))
51795
+ return "";
51796
+ const parts = [];
51797
+ for (const block of blocks) {
51798
+ const text = block?.text;
51799
+ if (typeof text === "string" && keep(text))
51800
+ parts.push(text);
51801
+ }
51802
+ return parts.join(`
51803
+ `);
51804
+ }
51805
+ function toolInputText(input) {
51806
+ let args = input;
51807
+ if (typeof input === "string") {
51808
+ try {
51809
+ args = JSON.parse(input);
51810
+ } catch {
51811
+ return input;
51812
+ }
51813
+ }
51814
+ const fields = args && typeof args === "object" ? args : {};
51815
+ const cmd = fields.cmd ?? fields.command;
51816
+ if (typeof cmd === "string")
51817
+ return cmd;
51818
+ if (Array.isArray(cmd))
51819
+ return cmd.join(" ");
51820
+ return typeof input === "string" ? input : JSON.stringify(input) ?? "";
51821
+ }
51822
+ function parseCodexRecord(entry, sessionId, filePath, fallbackTsMs) {
51823
+ const e = entry;
51824
+ const item = e?.type === "response_item" ? e.payload : undefined;
51825
+ if (!item)
51826
+ return;
51827
+ const toolName2 = typeof item.name === "string" ? item.name : "tool";
51828
+ let role = "assistant";
51829
+ let text;
51830
+ switch (item.type) {
51831
+ case "message":
51832
+ if (item.role !== "user" && item.role !== "assistant")
51833
+ return;
51834
+ role = item.role;
51835
+ text = blockText(item.content, item.role === "user" ? (t) => !INJECTED_CONTEXT_RE.test(t) : undefined);
51836
+ break;
51837
+ case "function_call":
51838
+ text = `[tool:${toolName2}] ${toolInputText(item.arguments)}`;
51839
+ break;
51840
+ case "custom_tool_call":
51841
+ text = `[tool:${toolName2}] ${typeof item.input === "string" ? item.input : ""}`;
51842
+ break;
51843
+ case "local_shell_call":
51844
+ text = `[tool:shell] ${toolInputText(item.action)}`;
51845
+ break;
51846
+ case "function_call_output":
51847
+ case "custom_tool_call_output": {
51848
+ role = "tool";
51849
+ const output = blockText(item.output);
51850
+ text = output ? `[tool_result] ${output}` : "";
51851
+ break;
51852
+ }
51853
+ default:
51854
+ return;
51855
+ }
51856
+ if (!text.trim())
51857
+ return;
51858
+ const ts = typeof e?.timestamp === "string" ? Date.parse(e.timestamp) || fallbackTsMs : fallbackTsMs;
51859
+ return { harness: "codex", text, ts, sessionId, role, filePath };
51860
+ }
51861
+
51862
+ class CodexProvider extends AbstractSessionLogProvider {
51863
+ name = "codex";
51864
+ availabilityRoot() {
51865
+ return codexSessionsDir();
51866
+ }
51867
+ listSessions(input = {}) {
51868
+ return this.listSessionsFromFiles({
51869
+ sinceMs: input.sinceMs ?? 0,
51870
+ enumerate: () => this.walkFiles(input.location ?? codexSessionsDir(), (name) => /^rollout-.+\.jsonl$/.test(name)),
51871
+ summarize: (rolloutPath, stat) => {
51872
+ const meta = this.#peekMeta(rolloutPath);
51873
+ if (meta?.isAgent)
51874
+ return;
51875
+ return this.sessionRef({
51876
+ sessionId: path43.basename(rolloutPath, ".jsonl").slice(-36),
51877
+ filePath: rolloutPath,
51878
+ startedAt: meta?.startedAt ?? stat.ctimeMs,
51879
+ endedAt: stat.mtimeMs,
51880
+ projectHint: meta?.cwd
51881
+ });
51882
+ }
51883
+ });
51884
+ }
51885
+ readSession(ref) {
51886
+ const stat = fs36.statSync(ref.filePath);
51887
+ const events = [];
51888
+ const inlineRefs = [];
51889
+ let meta;
51890
+ for (const line of fs36.readFileSync(ref.filePath, "utf8").split(`
51891
+ `).filter(Boolean)) {
51892
+ let entry;
51893
+ try {
51894
+ entry = JSON.parse(line);
51895
+ } catch {
51896
+ continue;
51897
+ }
51898
+ meta ??= parseSessionMeta(entry);
51899
+ const parsed = parseCodexRecord(entry, ref.sessionId, ref.filePath, stat.mtimeMs);
51900
+ if (!parsed)
51901
+ continue;
51902
+ events.push(parsed);
51903
+ inlineRefs.push(...extractInlineRefMentions(parsed.text, parsed.ts));
51904
+ }
51905
+ return {
51906
+ ref: this.sessionRef({
51907
+ sessionId: ref.sessionId,
51908
+ filePath: ref.filePath,
51909
+ startedAt: meta?.startedAt ?? events[0]?.ts ?? stat.ctimeMs,
51910
+ endedAt: events[events.length - 1]?.ts ?? stat.mtimeMs,
51911
+ projectHint: meta?.cwd
51912
+ }),
51913
+ events,
51914
+ inlineRefs
51915
+ };
51916
+ }
51917
+ #peekMeta(filePath) {
51918
+ try {
51919
+ const fd = fs36.openSync(filePath, "r");
51920
+ try {
51921
+ const head = Buffer.alloc(META_PEEK_BYTES);
51922
+ const firstLine = head.toString("utf8", 0, fs36.readSync(fd, head, 0, head.length, 0)).split(`
51923
+ `, 1)[0] ?? "";
51924
+ return parseSessionMeta(JSON.parse(firstLine));
51925
+ } finally {
51926
+ fs36.closeSync(fd);
51927
+ }
51928
+ } catch {
51929
+ return;
51930
+ }
51931
+ }
51932
+ }
51933
+
51770
51934
  // src/integrations/harnesses/codex/index.ts
51771
51935
  class CodexHarness extends BaseHarness {
51772
51936
  id = "codex";
@@ -51774,7 +51938,9 @@ class CodexHarness extends BaseHarness {
51774
51938
  agentBuilder = codexBuilder;
51775
51939
  resultExtractor = codexResultExtractor;
51776
51940
  presenceEnv = ["CODEX_SANDBOX"];
51941
+ sessionLogProvider = () => new CodexProvider;
51777
51942
  capabilities = caps({
51943
+ sessionLogs: true,
51778
51944
  agentDispatch: true,
51779
51945
  detection: true
51780
51946
  });
@@ -52095,7 +52261,7 @@ function opencodeInferenceConfig(inference, modelWork) {
52095
52261
  }
52096
52262
 
52097
52263
  // src/integrations/harnesses/opencode/model-work-agent.ts
52098
- import path43 from "node:path";
52264
+ import path44 from "node:path";
52099
52265
  var MODEL_WORK_OPENCODE_AGENT = "akm-model-work";
52100
52266
  var MODEL_WORK_PROMPT = "You do one bounded task for akm. Use tools only to check what the task needs, never repeat a tool call, and reply with exactly what the task asks for.";
52101
52267
  function modelWorkPermission(stash) {
@@ -52132,7 +52298,7 @@ function modelWorkPluginEnv() {
52132
52298
  AKM_AUTO_LEARNING: "0",
52133
52299
  AKM_AUTO_SKILL_PROPOSALS: "0",
52134
52300
  AKM_WRITE_GATE: "off",
52135
- XDG_STATE_HOME: path43.join(getStateDir(), "opencode-model-work"),
52301
+ XDG_STATE_HOME: path44.join(getStateDir(), "opencode-model-work"),
52136
52302
  ...process.platform === "win32" ? {} : { AKM_OPENCODE_CLI: "/bin/true" }
52137
52303
  };
52138
52304
  }
@@ -52215,15 +52381,15 @@ var opencodeBuilder = {
52215
52381
  };
52216
52382
 
52217
52383
  // src/integrations/harnesses/opencode/session-log.ts
52218
- import fs37 from "node:fs";
52219
- import os6 from "node:os";
52220
- import path45 from "node:path";
52384
+ import fs38 from "node:fs";
52385
+ import os7 from "node:os";
52386
+ import path46 from "node:path";
52221
52387
 
52222
52388
  // src/storage/sqlite-read-snapshot.ts
52223
52389
  import { spawnSync as spawnSync5 } from "node:child_process";
52224
- import fs36 from "node:fs";
52225
- import os5 from "node:os";
52226
- import path44 from "node:path";
52390
+ import fs37 from "node:fs";
52391
+ import os6 from "node:os";
52392
+ import path45 from "node:path";
52227
52393
  var SNAPSHOT_MAX_ATTEMPTS = 8;
52228
52394
  var SNAPSHOT_BACKOFF_MS = 25;
52229
52395
 
@@ -52235,7 +52401,7 @@ class SqliteReadSnapshotUnavailableError extends Error {
52235
52401
  }
52236
52402
  function pathExists(filePath) {
52237
52403
  try {
52238
- fs36.lstatSync(filePath);
52404
+ fs37.lstatSync(filePath);
52239
52405
  return true;
52240
52406
  } catch (error2) {
52241
52407
  if (error2.code === "ENOENT")
@@ -52245,7 +52411,7 @@ function pathExists(filePath) {
52245
52411
  }
52246
52412
  function fileFingerprint(filePath) {
52247
52413
  try {
52248
- const stat = fs36.statSync(filePath, { bigint: true });
52414
+ const stat = fs37.statSync(filePath, { bigint: true });
52249
52415
  return { size: stat.size, mtimeNs: stat.mtimeNs, ctimeNs: stat.ctimeNs };
52250
52416
  } catch (error2) {
52251
52417
  if (error2.code === "ENOENT")
@@ -52267,7 +52433,7 @@ function fingerprintsEqual(left, right) {
52267
52433
  }
52268
52434
  function copyFileOutsideThisProcess(source, destination) {
52269
52435
  if (process.platform === "win32") {
52270
- fs36.copyFileSync(source, destination);
52436
+ fs37.copyFileSync(source, destination);
52271
52437
  return;
52272
52438
  }
52273
52439
  const result = spawnSync5("cp", ["--", source, destination], {
@@ -52288,8 +52454,8 @@ function copyFileOutsideThisProcess(source, destination) {
52288
52454
  function openSqliteReadSnapshot(dbPath) {
52289
52455
  if (!pathExists(dbPath))
52290
52456
  return;
52291
- const snapshotDir = fs36.mkdtempSync(path44.join(os5.tmpdir(), "akm-sqlite-read-"));
52292
- const snapshotPath = path44.join(snapshotDir, "snapshot.db");
52457
+ const snapshotDir = fs37.mkdtempSync(path45.join(os6.tmpdir(), "akm-sqlite-read-"));
52458
+ const snapshotPath = path45.join(snapshotDir, "snapshot.db");
52293
52459
  let db;
52294
52460
  try {
52295
52461
  let copied = false;
@@ -52304,7 +52470,7 @@ function openSqliteReadSnapshot(dbPath) {
52304
52470
  if (before.wal)
52305
52471
  copyFileOutsideThisProcess(`${dbPath}-wal`, `${snapshotPath}-wal`);
52306
52472
  else
52307
- fs36.rmSync(`${snapshotPath}-wal`, { force: true });
52473
+ fs37.rmSync(`${snapshotPath}-wal`, { force: true });
52308
52474
  const after = databaseFingerprint(dbPath);
52309
52475
  if (fingerprintsEqual(before, after) && !pathExists(`${dbPath}-journal`)) {
52310
52476
  copied = true;
@@ -52332,14 +52498,14 @@ function openSqliteReadSnapshot(dbPath) {
52332
52498
  closeSnapshot();
52333
52499
  } catch {}
52334
52500
  try {
52335
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52501
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52336
52502
  } catch {}
52337
52503
  return;
52338
52504
  }
52339
52505
  try {
52340
52506
  closeSnapshot();
52341
52507
  } finally {
52342
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52508
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52343
52509
  }
52344
52510
  };
52345
52511
  const cleanupOnExit = () => cleanup(true);
@@ -52350,7 +52516,7 @@ function openSqliteReadSnapshot(dbPath) {
52350
52516
  try {
52351
52517
  db?.close();
52352
52518
  } finally {
52353
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52519
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52354
52520
  }
52355
52521
  throw error2;
52356
52522
  }
@@ -52359,9 +52525,9 @@ function openSqliteReadSnapshot(dbPath) {
52359
52525
  // src/integrations/harnesses/opencode/session-log.ts
52360
52526
  function getOpenCodeBaseDir() {
52361
52527
  if (process.platform === "darwin") {
52362
- return path45.join(os6.homedir(), "Library", "Application Support", "opencode");
52528
+ return path46.join(os7.homedir(), "Library", "Application Support", "opencode");
52363
52529
  }
52364
- return path45.join(os6.homedir(), ".local", "share", "opencode");
52530
+ return path46.join(os7.homedir(), ".local", "share", "opencode");
52365
52531
  }
52366
52532
  var OPENCODE_DB_FILENAME = "opencode.db";
52367
52533
 
@@ -52372,13 +52538,13 @@ class OpenCodeProvider extends AbstractSessionLogProvider {
52372
52538
  return this.#dbPath(this.#baseDir);
52373
52539
  }
52374
52540
  #dbPath(base) {
52375
- return path45.join(base, OPENCODE_DB_FILENAME);
52541
+ return path46.join(base, OPENCODE_DB_FILENAME);
52376
52542
  }
52377
52543
  listSessions(input = {}) {
52378
52544
  const base = input.location ?? this.#baseDir;
52379
52545
  const sinceMs = input.sinceMs ?? 0;
52380
52546
  const dbPath = this.#dbPath(base);
52381
- if (!fs37.existsSync(dbPath))
52547
+ if (!fs38.existsSync(dbPath))
52382
52548
  return [];
52383
52549
  return this.#listSessionsFromDb(dbPath, sinceMs, input.isolatedSnapshot ?? false);
52384
52550
  }
@@ -53287,8 +53453,8 @@ Commands:
53287
53453
  `;
53288
53454
 
53289
53455
  // scripts/akm-migrate/migrate/dead-residue.ts
53290
- import fs38 from "node:fs";
53291
- import path46 from "node:path";
53456
+ import fs39 from "node:fs";
53457
+ import path47 from "node:path";
53292
53458
  var DEAD_RESIDUE_PATHS = [
53293
53459
  { name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
53294
53460
  { prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
@@ -53305,43 +53471,43 @@ function dirSizeBytes(target) {
53305
53471
  let total = 0;
53306
53472
  let entries;
53307
53473
  try {
53308
- entries = fs38.readdirSync(target, { withFileTypes: true });
53474
+ entries = fs39.readdirSync(target, { withFileTypes: true });
53309
53475
  } catch {
53310
53476
  return 0;
53311
53477
  }
53312
53478
  for (const entry of entries) {
53313
- const entryPath = path46.join(target, entry.name);
53479
+ const entryPath = path47.join(target, entry.name);
53314
53480
  if (entry.isDirectory()) {
53315
53481
  total += dirSizeBytes(entryPath);
53316
53482
  } else if (entry.isFile()) {
53317
53483
  try {
53318
- total += fs38.statSync(entryPath).size;
53484
+ total += fs39.statSync(entryPath).size;
53319
53485
  } catch {}
53320
53486
  }
53321
53487
  }
53322
53488
  return total;
53323
53489
  }
53324
53490
  function sizeOf(target) {
53325
- const st = fs38.statSync(target);
53491
+ const st = fs39.statSync(target);
53326
53492
  return st.isDirectory() ? dirSizeBytes(target) : st.size;
53327
53493
  }
53328
53494
  function hostResidue() {
53329
53495
  const data = getDataDir();
53330
53496
  const state = getStateDir();
53331
- const configDir = path46.dirname(getConfigPath());
53497
+ const configDir = path47.dirname(getConfigPath());
53332
53498
  const named = [
53333
- { absolutePath: path46.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53334
- { absolutePath: path46.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53335
- { absolutePath: path46.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53336
- { absolutePath: path46.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53337
- { absolutePath: path46.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53338
- { absolutePath: path46.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53339
- { absolutePath: path46.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53499
+ { absolutePath: path47.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53500
+ { absolutePath: path47.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53501
+ { absolutePath: path47.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53502
+ { absolutePath: path47.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53503
+ { absolutePath: path47.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53504
+ { absolutePath: path47.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53505
+ { absolutePath: path47.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53340
53506
  ];
53341
53507
  const found = [];
53342
53508
  const claimed = new Set;
53343
53509
  for (const entry of named) {
53344
- if (claimed.has(entry.absolutePath) || !fs38.existsSync(entry.absolutePath))
53510
+ if (claimed.has(entry.absolutePath) || !fs39.existsSync(entry.absolutePath))
53345
53511
  continue;
53346
53512
  try {
53347
53513
  found.push({ ...entry, relativePath: entry.absolutePath, sizeBytes: sizeOf(entry.absolutePath) });
@@ -53365,13 +53531,13 @@ function hostResidue() {
53365
53531
  function findSidecars(root, depth, skip) {
53366
53532
  let entries;
53367
53533
  try {
53368
- entries = fs38.readdirSync(root, { withFileTypes: true });
53534
+ entries = fs39.readdirSync(root, { withFileTypes: true });
53369
53535
  } catch {
53370
53536
  return [];
53371
53537
  }
53372
53538
  const found = [];
53373
53539
  for (const entry of entries) {
53374
- const entryPath = path46.join(root, entry.name);
53540
+ const entryPath = path47.join(root, entry.name);
53375
53541
  if (entry.isFile() && entry.name.endsWith(".operations.sensitive"))
53376
53542
  found.push(entryPath);
53377
53543
  else if (entry.isDirectory() && depth > 0 && !skip.has(entryPath)) {
@@ -53384,10 +53550,10 @@ function findDeadResidueEntries(stashDir) {
53384
53550
  const host = hostResidue();
53385
53551
  if (stashDir === undefined)
53386
53552
  return host;
53387
- const akmDir = path46.join(stashDir, ".akm");
53553
+ const akmDir = path47.join(stashDir, ".akm");
53388
53554
  let names;
53389
53555
  try {
53390
- names = fs38.readdirSync(akmDir);
53556
+ names = fs39.readdirSync(akmDir);
53391
53557
  } catch {
53392
53558
  return [];
53393
53559
  }
@@ -53397,14 +53563,14 @@ function findDeadResidueEntries(stashDir) {
53397
53563
  for (const name of matches) {
53398
53564
  if (!names.includes(name))
53399
53565
  continue;
53400
- const absolutePath = path46.join(akmDir, name);
53566
+ const absolutePath = path47.join(akmDir, name);
53401
53567
  let sizeBytes;
53402
53568
  try {
53403
53569
  sizeBytes = sizeOf(absolutePath);
53404
53570
  } catch {
53405
53571
  continue;
53406
53572
  }
53407
- found.push({ relativePath: path46.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53573
+ found.push({ relativePath: path47.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53408
53574
  }
53409
53575
  }
53410
53576
  return found;
@@ -53413,7 +53579,7 @@ function removeDeadResidue(stashDir) {
53413
53579
  const entries = findDeadResidueEntries(stashDir);
53414
53580
  return entries.map((entry) => {
53415
53581
  try {
53416
- fs38.rmSync(entry.absolutePath, { recursive: true, force: true });
53582
+ fs39.rmSync(entry.absolutePath, { recursive: true, force: true });
53417
53583
  return { relativePath: entry.relativePath, sizeBytes: entry.sizeBytes, removed: true };
53418
53584
  } catch (error2) {
53419
53585
  return {
@@ -53428,18 +53594,18 @@ function removeDeadResidue(stashDir) {
53428
53594
 
53429
53595
  // scripts/akm-migrate/task-migrate.ts
53430
53596
  import { randomUUID as randomUUID3 } from "node:crypto";
53431
- import fs40 from "node:fs";
53432
- import os7 from "node:os";
53433
- import path49 from "node:path";
53597
+ import fs41 from "node:fs";
53598
+ import os8 from "node:os";
53599
+ import path50 from "node:path";
53434
53600
 
53435
53601
  // scripts/akm-migrate/migrate/task-files.ts
53436
53602
  import crypto4 from "node:crypto";
53437
- import fs39 from "node:fs";
53438
- import path48 from "node:path";
53603
+ import fs40 from "node:fs";
53604
+ import path49 from "node:path";
53439
53605
 
53440
53606
  // src/tasks/source/task-to-v4.ts
53441
53607
  import crypto3 from "node:crypto";
53442
- import path47 from "node:path";
53608
+ import path48 from "node:path";
53443
53609
 
53444
53610
  // src/tasks/task-id.ts
53445
53611
  var VALID_TASK_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -54248,7 +54414,7 @@ function addSharedNonPromptOverrides(data, akm) {
54248
54414
  }
54249
54415
  function promptSourceKind(raw) {
54250
54416
  const trimmed = raw.trim();
54251
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || path47.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54417
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || path48.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54252
54418
  return "file";
54253
54419
  }
54254
54420
  try {
@@ -54352,7 +54518,7 @@ function planV2DataToV4(input, data) {
54352
54518
  return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
54353
54519
  }
54354
54520
  try {
54355
- validateTaskId(path47.basename(input.filePath, ".yml"));
54521
+ validateTaskId(path48.basename(input.filePath, ".yml"));
54356
54522
  } catch (cause) {
54357
54523
  return blocked(input, "invalid-v2-task", causeMessage(cause));
54358
54524
  }
@@ -54497,7 +54663,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
54497
54663
  for (let index = 1;index < files.length; index += 1) {
54498
54664
  const previous = files[index - 1];
54499
54665
  const current = files[index];
54500
- if (previous && current && path47.resolve(previous.filePath) === path47.resolve(current.filePath)) {
54666
+ if (previous && current && path48.resolve(previous.filePath) === path48.resolve(current.filePath)) {
54501
54667
  throw new Error(`duplicate task migration file path: ${current.filePath}`);
54502
54668
  }
54503
54669
  }
@@ -54509,18 +54675,18 @@ function migrationError(detail) {
54509
54675
  return new ConfigError(`Task migration failed: ${detail}`, "INVALID_CONFIG_FILE");
54510
54676
  }
54511
54677
  function contained2(root, candidate) {
54512
- const relative = path48.relative(root, candidate);
54513
- return relative === "" || !relative.startsWith("..") && !path48.isAbsolute(relative);
54678
+ const relative = path49.relative(root, candidate);
54679
+ return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
54514
54680
  }
54515
54681
  function realDirectory(filePath) {
54516
- const stat = fs39.lstatSync(filePath);
54682
+ const stat = fs40.lstatSync(filePath);
54517
54683
  if (stat.isSymbolicLink() || !stat.isDirectory())
54518
54684
  throw migrationError(`${filePath} must be a real directory.`);
54519
- return fs39.realpathSync(filePath);
54685
+ return fs40.realpathSync(filePath);
54520
54686
  }
54521
54687
  function isWritable(filePath) {
54522
54688
  try {
54523
- fs39.accessSync(filePath, fs39.constants.W_OK);
54689
+ fs40.accessSync(filePath, fs40.constants.W_OK);
54524
54690
  return true;
54525
54691
  } catch {
54526
54692
  return false;
@@ -54533,12 +54699,12 @@ function walkTasks(root, tasksDir, out) {
54533
54699
  throw migrationError(`${root.root} resolves outside bundle ${root.bundleId}.`);
54534
54700
  }
54535
54701
  const visit2 = (directory) => {
54536
- const physicalDirectory = fs39.realpathSync(directory);
54702
+ const physicalDirectory = fs40.realpathSync(directory);
54537
54703
  if (!contained2(physicalRoot, physicalDirectory)) {
54538
54704
  throw migrationError(`${directory} resolves outside bundle ${root.bundleId}.`);
54539
54705
  }
54540
- for (const entry of fs39.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54541
- const candidate = path48.join(directory, entry.name);
54706
+ for (const entry of fs40.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54707
+ const candidate = path49.join(directory, entry.name);
54542
54708
  if (entry.isSymbolicLink())
54543
54709
  throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
54544
54710
  if (entry.isDirectory()) {
@@ -54547,11 +54713,11 @@ function walkTasks(root, tasksDir, out) {
54547
54713
  }
54548
54714
  if (!entry.isFile() || !entry.name.endsWith(".yml"))
54549
54715
  continue;
54550
- const stat = fs39.lstatSync(candidate);
54716
+ const stat = fs40.lstatSync(candidate);
54551
54717
  const mode = stat.mode & 511;
54552
54718
  out.push({
54553
54719
  filePath: candidate,
54554
- bytes: fs39.readFileSync(candidate),
54720
+ bytes: fs40.readFileSync(candidate),
54555
54721
  mode,
54556
54722
  writable: root.writable,
54557
54723
  onDiskWritable: isWritable(candidate) && isWritable(directory) && (mode & 146) !== 0,
@@ -54564,9 +54730,9 @@ function walkTasks(root, tasksDir, out) {
54564
54730
  function inspectTaskFiles(roots) {
54565
54731
  const files = [];
54566
54732
  for (const root of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
54567
- const tasksDir = root.layout === "akm-task" ? root.root : path48.join(root.root, "tasks");
54733
+ const tasksDir = root.layout === "akm-task" ? root.root : path49.join(root.root, "tasks");
54568
54734
  try {
54569
- const stat = fs39.lstatSync(tasksDir);
54735
+ const stat = fs40.lstatSync(tasksDir);
54570
54736
  if (stat.isSymbolicLink())
54571
54737
  throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
54572
54738
  if (!stat.isDirectory())
@@ -54584,18 +54750,18 @@ function planTaskFilesMigration(inputs) {
54584
54750
  return taskToV4PlanFromOutcomes(inputs.map(planTaskToV4File));
54585
54751
  }
54586
54752
  function taskFileBackupPath(backupRoot, filePath) {
54587
- const digest = crypto4.createHash("sha256").update(path48.resolve(filePath)).digest("hex").slice(0, 16);
54588
- return path48.join(backupRoot, "files", `${digest}-${path48.basename(filePath)}`);
54753
+ const digest = crypto4.createHash("sha256").update(path49.resolve(filePath)).digest("hex").slice(0, 16);
54754
+ return path49.join(backupRoot, "files", `${digest}-${path49.basename(filePath)}`);
54589
54755
  }
54590
54756
  function fsyncDirectory(directory) {
54591
54757
  if (process.platform === "win32")
54592
54758
  return;
54593
54759
  try {
54594
- const fd = fs39.openSync(directory, "r");
54760
+ const fd = fs40.openSync(directory, "r");
54595
54761
  try {
54596
- fs39.fsyncSync(fd);
54762
+ fs40.fsyncSync(fd);
54597
54763
  } finally {
54598
- fs39.closeSync(fd);
54764
+ fs40.closeSync(fd);
54599
54765
  }
54600
54766
  } catch (cause) {
54601
54767
  const code = cause.code;
@@ -54604,25 +54770,25 @@ function fsyncDirectory(directory) {
54604
54770
  }
54605
54771
  }
54606
54772
  function writeDurable(filePath, bytes, mode, exclusive = false) {
54607
- fs39.mkdirSync(path48.dirname(filePath), { recursive: true });
54608
- const fd = fs39.openSync(filePath, exclusive ? "wx" : "w", mode);
54773
+ fs40.mkdirSync(path49.dirname(filePath), { recursive: true });
54774
+ const fd = fs40.openSync(filePath, exclusive ? "wx" : "w", mode);
54609
54775
  try {
54610
- fs39.writeFileSync(fd, bytes);
54611
- fs39.fsyncSync(fd);
54776
+ fs40.writeFileSync(fd, bytes);
54777
+ fs40.fsyncSync(fd);
54612
54778
  } finally {
54613
- fs39.closeSync(fd);
54779
+ fs40.closeSync(fd);
54614
54780
  }
54615
- fs39.chmodSync(filePath, mode);
54616
- fsyncDirectory(path48.dirname(filePath));
54781
+ fs40.chmodSync(filePath, mode);
54782
+ fsyncDirectory(path49.dirname(filePath));
54617
54783
  }
54618
54784
  function replaceAtomically(filePath, bytes, mode) {
54619
- const temporary = path48.join(path48.dirname(filePath), `.${path48.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54785
+ const temporary = path49.join(path49.dirname(filePath), `.${path49.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54620
54786
  try {
54621
54787
  writeDurable(temporary, bytes, mode, true);
54622
- fs39.renameSync(temporary, filePath);
54623
- fsyncDirectory(path48.dirname(filePath));
54788
+ fs40.renameSync(temporary, filePath);
54789
+ fsyncDirectory(path49.dirname(filePath));
54624
54790
  } finally {
54625
- fs39.rmSync(temporary, { force: true });
54791
+ fs40.rmSync(temporary, { force: true });
54626
54792
  }
54627
54793
  }
54628
54794
  function applyTaskFilesPlan(plan, options) {
@@ -54645,7 +54811,7 @@ function applyTaskFilesPlan(plan, options) {
54645
54811
  }
54646
54812
  } catch (cause) {
54647
54813
  for (const change of [...replaced].reverse()) {
54648
- replaceAtomically(change.filePath, fs39.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54814
+ replaceAtomically(change.filePath, fs40.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54649
54815
  }
54650
54816
  throw cause;
54651
54817
  }
@@ -54655,14 +54821,14 @@ function applyTaskFilesPlan(plan, options) {
54655
54821
  // scripts/akm-migrate/task-migrate.ts
54656
54822
  function expandTilde(value) {
54657
54823
  if (value === "~")
54658
- return os7.homedir();
54824
+ return os8.homedir();
54659
54825
  if (value.startsWith("~/") || value.startsWith("~\\"))
54660
- return path49.join(os7.homedir(), value.slice(2));
54826
+ return path50.join(os8.homedir(), value.slice(2));
54661
54827
  return value;
54662
54828
  }
54663
54829
  function existingDirectory(target) {
54664
54830
  try {
54665
- return fs40.statSync(target).isDirectory();
54831
+ return fs41.statSync(target).isDirectory();
54666
54832
  } catch (cause) {
54667
54833
  if (cause.code === "ENOENT")
54668
54834
  return false;
@@ -54683,14 +54849,14 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54683
54849
  const source = sources.get(bundleId);
54684
54850
  if (!source)
54685
54851
  continue;
54686
- const configuredRoot = source.type === "filesystem" && source.path ? path49.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54852
+ const configuredRoot = source.type === "filesystem" && source.path ? path50.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54687
54853
  if (!configuredRoot || !existingDirectory(configuredRoot))
54688
54854
  continue;
54689
- const bundleRoot = path49.resolve(configuredRoot);
54855
+ const bundleRoot = path50.resolve(configuredRoot);
54690
54856
  const component = bundleComponentConfig(bundle);
54691
- const componentRoot = path49.resolve(bundleRoot, component?.root ?? ".");
54692
- const relative = path49.relative(bundleRoot, componentRoot);
54693
- if (relative === ".." || relative.startsWith(`..${path49.sep}`) || path49.isAbsolute(relative)) {
54857
+ const componentRoot = path50.resolve(bundleRoot, component?.root ?? ".");
54858
+ const relative = path50.relative(bundleRoot, componentRoot);
54859
+ if (relative === ".." || relative.startsWith(`..${path50.sep}`) || path50.isAbsolute(relative)) {
54694
54860
  throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
54695
54861
  }
54696
54862
  if (!existingDirectory(componentRoot))
@@ -54707,7 +54873,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54707
54873
  }
54708
54874
  const envStash = process.env.AKM_BUNDLE_DIR?.trim();
54709
54875
  if (envStash && existingDirectory(envStash)) {
54710
- const stashRoot = path49.resolve(envStash);
54876
+ const stashRoot = path50.resolve(envStash);
54711
54877
  if (!rootsByPath.has(stashRoot)) {
54712
54878
  const bundleId = deriveBundleId(undefined, stashRoot, new Set(Object.keys(config.bundles ?? {})));
54713
54879
  const candidate = taskRoot(bundleId, stashRoot, stashRoot, detectAdapterId(stashRoot), () => true);
@@ -54720,7 +54886,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54720
54886
  function taskRoot(bundleId, bundleRoot, componentRoot, configuredAdapter, writable) {
54721
54887
  const adapter = configuredAdapter ?? detectAdapterId(componentRoot, "");
54722
54888
  if (!configuredAdapter && adapter === "") {
54723
- const flatTasks = fs40.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54889
+ const flatTasks = fs41.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54724
54890
  if (flatTasks.length > 0) {
54725
54891
  throw new ConfigError(`Task migration cannot classify top-level task file(s) ${flatTasks.join(", ")} in bundle ${bundleId}; configure adapter "akm-task" or move them under tasks/.`, "INVALID_CONFIG_FILE");
54726
54892
  }
@@ -54776,7 +54942,7 @@ function applyTaskFilesMigration() {
54776
54942
  const before = inspectCurrent();
54777
54943
  if (before.result.taskFiles.changed === 0)
54778
54944
  return before.result;
54779
- const backupPath = path49.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54945
+ const backupPath = path50.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54780
54946
  const applied = applyTaskFilesPlan(before.plan, { backupRoot: backupPath });
54781
54947
  return { ...inspectCurrent().result, backupPath, applied: applied.changed.length };
54782
54948
  });