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.
@@ -51762,6 +51762,170 @@ var codexResultExtractor = (result) => {
51762
51762
  return sessionId === undefined ? { text } : { text, sessionId };
51763
51763
  };
51764
51764
 
51765
+ // src/integrations/harnesses/codex/session-log.ts
51766
+ import fs36 from "fs";
51767
+ import os5 from "os";
51768
+ import path43 from "path";
51769
+ function codexSessionsDir() {
51770
+ return path43.join(process.env.CODEX_HOME || path43.join(os5.homedir(), ".codex"), "sessions");
51771
+ }
51772
+ var META_PEEK_BYTES = 128 * 1024;
51773
+ 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;
51774
+ function parseSessionMeta(entry) {
51775
+ const e = entry;
51776
+ if (e?.type !== "session_meta" || !e.payload)
51777
+ return;
51778
+ const { timestamp, cwd, source } = e.payload;
51779
+ const startedAt = typeof timestamp === "string" ? Date.parse(timestamp) : Number.NaN;
51780
+ return {
51781
+ ...Number.isNaN(startedAt) ? {} : { startedAt },
51782
+ ...typeof cwd === "string" ? { cwd } : {},
51783
+ isAgent: typeof source === "object" && source !== null && (("subagent" in source) || ("internal" in source))
51784
+ };
51785
+ }
51786
+ function blockText(blocks, keep = () => true) {
51787
+ if (typeof blocks === "string")
51788
+ return blocks;
51789
+ if (!Array.isArray(blocks))
51790
+ return "";
51791
+ const parts = [];
51792
+ for (const block of blocks) {
51793
+ const text = block?.text;
51794
+ if (typeof text === "string" && keep(text))
51795
+ parts.push(text);
51796
+ }
51797
+ return parts.join(`
51798
+ `);
51799
+ }
51800
+ function toolInputText(input) {
51801
+ let args = input;
51802
+ if (typeof input === "string") {
51803
+ try {
51804
+ args = JSON.parse(input);
51805
+ } catch {
51806
+ return input;
51807
+ }
51808
+ }
51809
+ const fields = args && typeof args === "object" ? args : {};
51810
+ const cmd = fields.cmd ?? fields.command;
51811
+ if (typeof cmd === "string")
51812
+ return cmd;
51813
+ if (Array.isArray(cmd))
51814
+ return cmd.join(" ");
51815
+ return typeof input === "string" ? input : JSON.stringify(input) ?? "";
51816
+ }
51817
+ function parseCodexRecord(entry, sessionId, filePath, fallbackTsMs) {
51818
+ const e = entry;
51819
+ const item = e?.type === "response_item" ? e.payload : undefined;
51820
+ if (!item)
51821
+ return;
51822
+ const toolName2 = typeof item.name === "string" ? item.name : "tool";
51823
+ let role = "assistant";
51824
+ let text;
51825
+ switch (item.type) {
51826
+ case "message":
51827
+ if (item.role !== "user" && item.role !== "assistant")
51828
+ return;
51829
+ role = item.role;
51830
+ text = blockText(item.content, item.role === "user" ? (t) => !INJECTED_CONTEXT_RE.test(t) : undefined);
51831
+ break;
51832
+ case "function_call":
51833
+ text = `[tool:${toolName2}] ${toolInputText(item.arguments)}`;
51834
+ break;
51835
+ case "custom_tool_call":
51836
+ text = `[tool:${toolName2}] ${typeof item.input === "string" ? item.input : ""}`;
51837
+ break;
51838
+ case "local_shell_call":
51839
+ text = `[tool:shell] ${toolInputText(item.action)}`;
51840
+ break;
51841
+ case "function_call_output":
51842
+ case "custom_tool_call_output": {
51843
+ role = "tool";
51844
+ const output = blockText(item.output);
51845
+ text = output ? `[tool_result] ${output}` : "";
51846
+ break;
51847
+ }
51848
+ default:
51849
+ return;
51850
+ }
51851
+ if (!text.trim())
51852
+ return;
51853
+ const ts = typeof e?.timestamp === "string" ? Date.parse(e.timestamp) || fallbackTsMs : fallbackTsMs;
51854
+ return { harness: "codex", text, ts, sessionId, role, filePath };
51855
+ }
51856
+
51857
+ class CodexProvider extends AbstractSessionLogProvider {
51858
+ name = "codex";
51859
+ availabilityRoot() {
51860
+ return codexSessionsDir();
51861
+ }
51862
+ listSessions(input = {}) {
51863
+ return this.listSessionsFromFiles({
51864
+ sinceMs: input.sinceMs ?? 0,
51865
+ enumerate: () => this.walkFiles(input.location ?? codexSessionsDir(), (name) => /^rollout-.+\.jsonl$/.test(name)),
51866
+ summarize: (rolloutPath, stat) => {
51867
+ const meta = this.#peekMeta(rolloutPath);
51868
+ if (meta?.isAgent)
51869
+ return;
51870
+ return this.sessionRef({
51871
+ sessionId: path43.basename(rolloutPath, ".jsonl").slice(-36),
51872
+ filePath: rolloutPath,
51873
+ startedAt: meta?.startedAt ?? stat.ctimeMs,
51874
+ endedAt: stat.mtimeMs,
51875
+ projectHint: meta?.cwd
51876
+ });
51877
+ }
51878
+ });
51879
+ }
51880
+ readSession(ref) {
51881
+ const stat = fs36.statSync(ref.filePath);
51882
+ const events = [];
51883
+ const inlineRefs = [];
51884
+ let meta;
51885
+ for (const line of fs36.readFileSync(ref.filePath, "utf8").split(`
51886
+ `).filter(Boolean)) {
51887
+ let entry;
51888
+ try {
51889
+ entry = JSON.parse(line);
51890
+ } catch {
51891
+ continue;
51892
+ }
51893
+ meta ??= parseSessionMeta(entry);
51894
+ const parsed = parseCodexRecord(entry, ref.sessionId, ref.filePath, stat.mtimeMs);
51895
+ if (!parsed)
51896
+ continue;
51897
+ events.push(parsed);
51898
+ inlineRefs.push(...extractInlineRefMentions(parsed.text, parsed.ts));
51899
+ }
51900
+ return {
51901
+ ref: this.sessionRef({
51902
+ sessionId: ref.sessionId,
51903
+ filePath: ref.filePath,
51904
+ startedAt: meta?.startedAt ?? events[0]?.ts ?? stat.ctimeMs,
51905
+ endedAt: events[events.length - 1]?.ts ?? stat.mtimeMs,
51906
+ projectHint: meta?.cwd
51907
+ }),
51908
+ events,
51909
+ inlineRefs
51910
+ };
51911
+ }
51912
+ #peekMeta(filePath) {
51913
+ try {
51914
+ const fd = fs36.openSync(filePath, "r");
51915
+ try {
51916
+ const head = Buffer.alloc(META_PEEK_BYTES);
51917
+ const firstLine = head.toString("utf8", 0, fs36.readSync(fd, head, 0, head.length, 0)).split(`
51918
+ `, 1)[0] ?? "";
51919
+ return parseSessionMeta(JSON.parse(firstLine));
51920
+ } finally {
51921
+ fs36.closeSync(fd);
51922
+ }
51923
+ } catch {
51924
+ return;
51925
+ }
51926
+ }
51927
+ }
51928
+
51765
51929
  // src/integrations/harnesses/codex/index.ts
51766
51930
  class CodexHarness extends BaseHarness {
51767
51931
  id = "codex";
@@ -51769,7 +51933,9 @@ class CodexHarness extends BaseHarness {
51769
51933
  agentBuilder = codexBuilder;
51770
51934
  resultExtractor = codexResultExtractor;
51771
51935
  presenceEnv = ["CODEX_SANDBOX"];
51936
+ sessionLogProvider = () => new CodexProvider;
51772
51937
  capabilities = caps({
51938
+ sessionLogs: true,
51773
51939
  agentDispatch: true,
51774
51940
  detection: true
51775
51941
  });
@@ -52090,7 +52256,7 @@ function opencodeInferenceConfig(inference, modelWork) {
52090
52256
  }
52091
52257
 
52092
52258
  // src/integrations/harnesses/opencode/model-work-agent.ts
52093
- import path43 from "path";
52259
+ import path44 from "path";
52094
52260
  var MODEL_WORK_OPENCODE_AGENT = "akm-model-work";
52095
52261
  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.";
52096
52262
  function modelWorkPermission(stash) {
@@ -52127,7 +52293,7 @@ function modelWorkPluginEnv() {
52127
52293
  AKM_AUTO_LEARNING: "0",
52128
52294
  AKM_AUTO_SKILL_PROPOSALS: "0",
52129
52295
  AKM_WRITE_GATE: "off",
52130
- XDG_STATE_HOME: path43.join(getStateDir(), "opencode-model-work"),
52296
+ XDG_STATE_HOME: path44.join(getStateDir(), "opencode-model-work"),
52131
52297
  ...process.platform === "win32" ? {} : { AKM_OPENCODE_CLI: "/bin/true" }
52132
52298
  };
52133
52299
  }
@@ -52210,15 +52376,15 @@ var opencodeBuilder = {
52210
52376
  };
52211
52377
 
52212
52378
  // src/integrations/harnesses/opencode/session-log.ts
52213
- import fs37 from "fs";
52214
- import os6 from "os";
52215
- import path45 from "path";
52379
+ import fs38 from "fs";
52380
+ import os7 from "os";
52381
+ import path46 from "path";
52216
52382
 
52217
52383
  // src/storage/sqlite-read-snapshot.ts
52218
52384
  import { spawnSync as spawnSync5 } from "child_process";
52219
- import fs36 from "fs";
52220
- import os5 from "os";
52221
- import path44 from "path";
52385
+ import fs37 from "fs";
52386
+ import os6 from "os";
52387
+ import path45 from "path";
52222
52388
  var SNAPSHOT_MAX_ATTEMPTS = 8;
52223
52389
  var SNAPSHOT_BACKOFF_MS = 25;
52224
52390
 
@@ -52230,7 +52396,7 @@ class SqliteReadSnapshotUnavailableError extends Error {
52230
52396
  }
52231
52397
  function pathExists(filePath) {
52232
52398
  try {
52233
- fs36.lstatSync(filePath);
52399
+ fs37.lstatSync(filePath);
52234
52400
  return true;
52235
52401
  } catch (error2) {
52236
52402
  if (error2.code === "ENOENT")
@@ -52240,7 +52406,7 @@ function pathExists(filePath) {
52240
52406
  }
52241
52407
  function fileFingerprint(filePath) {
52242
52408
  try {
52243
- const stat = fs36.statSync(filePath, { bigint: true });
52409
+ const stat = fs37.statSync(filePath, { bigint: true });
52244
52410
  return { size: stat.size, mtimeNs: stat.mtimeNs, ctimeNs: stat.ctimeNs };
52245
52411
  } catch (error2) {
52246
52412
  if (error2.code === "ENOENT")
@@ -52262,7 +52428,7 @@ function fingerprintsEqual(left, right) {
52262
52428
  }
52263
52429
  function copyFileOutsideThisProcess(source, destination) {
52264
52430
  if (process.platform === "win32") {
52265
- fs36.copyFileSync(source, destination);
52431
+ fs37.copyFileSync(source, destination);
52266
52432
  return;
52267
52433
  }
52268
52434
  const result = spawnSync5("cp", ["--", source, destination], {
@@ -52283,8 +52449,8 @@ function copyFileOutsideThisProcess(source, destination) {
52283
52449
  function openSqliteReadSnapshot(dbPath) {
52284
52450
  if (!pathExists(dbPath))
52285
52451
  return;
52286
- const snapshotDir = fs36.mkdtempSync(path44.join(os5.tmpdir(), "akm-sqlite-read-"));
52287
- const snapshotPath = path44.join(snapshotDir, "snapshot.db");
52452
+ const snapshotDir = fs37.mkdtempSync(path45.join(os6.tmpdir(), "akm-sqlite-read-"));
52453
+ const snapshotPath = path45.join(snapshotDir, "snapshot.db");
52288
52454
  let db;
52289
52455
  try {
52290
52456
  let copied = false;
@@ -52299,7 +52465,7 @@ function openSqliteReadSnapshot(dbPath) {
52299
52465
  if (before.wal)
52300
52466
  copyFileOutsideThisProcess(`${dbPath}-wal`, `${snapshotPath}-wal`);
52301
52467
  else
52302
- fs36.rmSync(`${snapshotPath}-wal`, { force: true });
52468
+ fs37.rmSync(`${snapshotPath}-wal`, { force: true });
52303
52469
  const after = databaseFingerprint(dbPath);
52304
52470
  if (fingerprintsEqual(before, after) && !pathExists(`${dbPath}-journal`)) {
52305
52471
  copied = true;
@@ -52327,14 +52493,14 @@ function openSqliteReadSnapshot(dbPath) {
52327
52493
  closeSnapshot();
52328
52494
  } catch {}
52329
52495
  try {
52330
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52496
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52331
52497
  } catch {}
52332
52498
  return;
52333
52499
  }
52334
52500
  try {
52335
52501
  closeSnapshot();
52336
52502
  } finally {
52337
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52503
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52338
52504
  }
52339
52505
  };
52340
52506
  const cleanupOnExit = () => cleanup(true);
@@ -52345,7 +52511,7 @@ function openSqliteReadSnapshot(dbPath) {
52345
52511
  try {
52346
52512
  db?.close();
52347
52513
  } finally {
52348
- fs36.rmSync(snapshotDir, { recursive: true, force: true });
52514
+ fs37.rmSync(snapshotDir, { recursive: true, force: true });
52349
52515
  }
52350
52516
  throw error2;
52351
52517
  }
@@ -52354,9 +52520,9 @@ function openSqliteReadSnapshot(dbPath) {
52354
52520
  // src/integrations/harnesses/opencode/session-log.ts
52355
52521
  function getOpenCodeBaseDir() {
52356
52522
  if (process.platform === "darwin") {
52357
- return path45.join(os6.homedir(), "Library", "Application Support", "opencode");
52523
+ return path46.join(os7.homedir(), "Library", "Application Support", "opencode");
52358
52524
  }
52359
- return path45.join(os6.homedir(), ".local", "share", "opencode");
52525
+ return path46.join(os7.homedir(), ".local", "share", "opencode");
52360
52526
  }
52361
52527
  var OPENCODE_DB_FILENAME = "opencode.db";
52362
52528
 
@@ -52367,13 +52533,13 @@ class OpenCodeProvider extends AbstractSessionLogProvider {
52367
52533
  return this.#dbPath(this.#baseDir);
52368
52534
  }
52369
52535
  #dbPath(base) {
52370
- return path45.join(base, OPENCODE_DB_FILENAME);
52536
+ return path46.join(base, OPENCODE_DB_FILENAME);
52371
52537
  }
52372
52538
  listSessions(input = {}) {
52373
52539
  const base = input.location ?? this.#baseDir;
52374
52540
  const sinceMs = input.sinceMs ?? 0;
52375
52541
  const dbPath = this.#dbPath(base);
52376
- if (!fs37.existsSync(dbPath))
52542
+ if (!fs38.existsSync(dbPath))
52377
52543
  return [];
52378
52544
  return this.#listSessionsFromDb(dbPath, sinceMs, input.isolatedSnapshot ?? false);
52379
52545
  }
@@ -53245,8 +53411,8 @@ Commands:
53245
53411
  `;
53246
53412
 
53247
53413
  // scripts/akm-migrate/migrate/dead-residue.ts
53248
- import fs38 from "fs";
53249
- import path46 from "path";
53414
+ import fs39 from "fs";
53415
+ import path47 from "path";
53250
53416
  var DEAD_RESIDUE_PATHS = [
53251
53417
  { name: "proposals", reason: "superseded by the `proposals` table in $DATA/state.db (0.9.0)" },
53252
53418
  { prefix: "runs.archived-", reason: "orphaned archive of a directory that no longer exists" },
@@ -53263,43 +53429,43 @@ function dirSizeBytes(target) {
53263
53429
  let total = 0;
53264
53430
  let entries;
53265
53431
  try {
53266
- entries = fs38.readdirSync(target, { withFileTypes: true });
53432
+ entries = fs39.readdirSync(target, { withFileTypes: true });
53267
53433
  } catch {
53268
53434
  return 0;
53269
53435
  }
53270
53436
  for (const entry of entries) {
53271
- const entryPath = path46.join(target, entry.name);
53437
+ const entryPath = path47.join(target, entry.name);
53272
53438
  if (entry.isDirectory()) {
53273
53439
  total += dirSizeBytes(entryPath);
53274
53440
  } else if (entry.isFile()) {
53275
53441
  try {
53276
- total += fs38.statSync(entryPath).size;
53442
+ total += fs39.statSync(entryPath).size;
53277
53443
  } catch {}
53278
53444
  }
53279
53445
  }
53280
53446
  return total;
53281
53447
  }
53282
53448
  function sizeOf(target) {
53283
- const st = fs38.statSync(target);
53449
+ const st = fs39.statSync(target);
53284
53450
  return st.isDirectory() ? dirSizeBytes(target) : st.size;
53285
53451
  }
53286
53452
  function hostResidue() {
53287
53453
  const data = getDataDir();
53288
53454
  const state = getStateDir();
53289
- const configDir = path46.dirname(getConfigPath());
53455
+ const configDir = path47.dirname(getConfigPath());
53290
53456
  const named = [
53291
- { absolutePath: path46.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53292
- { absolutePath: path46.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53293
- { absolutePath: path46.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53294
- { absolutePath: path46.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53295
- { absolutePath: path46.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53296
- { absolutePath: path46.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53297
- { absolutePath: path46.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53457
+ { absolutePath: path47.join(data, "txn"), reason: "filesystem transaction journals (removed in 0.9.17)" },
53458
+ { absolutePath: path47.join(data, "txn-quarantine"), reason: "quarantined transaction journals (removed in 0.9.17)" },
53459
+ { absolutePath: path47.join(data, "maintenance.barrier.lock"), reason: "maintenance barrier (removed in 0.9.17)" },
53460
+ { absolutePath: path47.join(data, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53461
+ { absolutePath: path47.join(state, "maintenance-activities"), reason: "per-process activity registry (removed in 0.9.17)" },
53462
+ { absolutePath: path47.join(state, "version-reconcile.json"), reason: "startup reconcile stamp (removed in 0.9.17)" },
53463
+ { absolutePath: path47.join(state, "locks", "version-reconcile.lock"), reason: "startup reconcile lock (removed in 0.9.17)" }
53298
53464
  ];
53299
53465
  const found = [];
53300
53466
  const claimed = new Set;
53301
53467
  for (const entry of named) {
53302
- if (claimed.has(entry.absolutePath) || !fs38.existsSync(entry.absolutePath))
53468
+ if (claimed.has(entry.absolutePath) || !fs39.existsSync(entry.absolutePath))
53303
53469
  continue;
53304
53470
  try {
53305
53471
  found.push({ ...entry, relativePath: entry.absolutePath, sizeBytes: sizeOf(entry.absolutePath) });
@@ -53323,13 +53489,13 @@ function hostResidue() {
53323
53489
  function findSidecars(root2, depth, skip) {
53324
53490
  let entries;
53325
53491
  try {
53326
- entries = fs38.readdirSync(root2, { withFileTypes: true });
53492
+ entries = fs39.readdirSync(root2, { withFileTypes: true });
53327
53493
  } catch {
53328
53494
  return [];
53329
53495
  }
53330
53496
  const found = [];
53331
53497
  for (const entry of entries) {
53332
- const entryPath = path46.join(root2, entry.name);
53498
+ const entryPath = path47.join(root2, entry.name);
53333
53499
  if (entry.isFile() && entry.name.endsWith(".operations.sensitive"))
53334
53500
  found.push(entryPath);
53335
53501
  else if (entry.isDirectory() && depth > 0 && !skip.has(entryPath)) {
@@ -53342,10 +53508,10 @@ function findDeadResidueEntries(stashDir) {
53342
53508
  const host = hostResidue();
53343
53509
  if (stashDir === undefined)
53344
53510
  return host;
53345
- const akmDir = path46.join(stashDir, ".akm");
53511
+ const akmDir = path47.join(stashDir, ".akm");
53346
53512
  let names;
53347
53513
  try {
53348
- names = fs38.readdirSync(akmDir);
53514
+ names = fs39.readdirSync(akmDir);
53349
53515
  } catch {
53350
53516
  return [];
53351
53517
  }
@@ -53355,14 +53521,14 @@ function findDeadResidueEntries(stashDir) {
53355
53521
  for (const name of matches) {
53356
53522
  if (!names.includes(name))
53357
53523
  continue;
53358
- const absolutePath = path46.join(akmDir, name);
53524
+ const absolutePath = path47.join(akmDir, name);
53359
53525
  let sizeBytes;
53360
53526
  try {
53361
53527
  sizeBytes = sizeOf(absolutePath);
53362
53528
  } catch {
53363
53529
  continue;
53364
53530
  }
53365
- found.push({ relativePath: path46.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53531
+ found.push({ relativePath: path47.join(".akm", name), absolutePath, sizeBytes, reason: spec.reason });
53366
53532
  }
53367
53533
  }
53368
53534
  return found;
@@ -53371,7 +53537,7 @@ function removeDeadResidue(stashDir) {
53371
53537
  const entries = findDeadResidueEntries(stashDir);
53372
53538
  return entries.map((entry) => {
53373
53539
  try {
53374
- fs38.rmSync(entry.absolutePath, { recursive: true, force: true });
53540
+ fs39.rmSync(entry.absolutePath, { recursive: true, force: true });
53375
53541
  return { relativePath: entry.relativePath, sizeBytes: entry.sizeBytes, removed: true };
53376
53542
  } catch (error2) {
53377
53543
  return {
@@ -53386,18 +53552,18 @@ function removeDeadResidue(stashDir) {
53386
53552
 
53387
53553
  // scripts/akm-migrate/task-migrate.ts
53388
53554
  import { randomUUID as randomUUID3 } from "crypto";
53389
- import fs40 from "fs";
53390
- import os7 from "os";
53391
- import path49 from "path";
53555
+ import fs41 from "fs";
53556
+ import os8 from "os";
53557
+ import path50 from "path";
53392
53558
 
53393
53559
  // scripts/akm-migrate/migrate/task-files.ts
53394
53560
  import crypto4 from "crypto";
53395
- import fs39 from "fs";
53396
- import path48 from "path";
53561
+ import fs40 from "fs";
53562
+ import path49 from "path";
53397
53563
 
53398
53564
  // src/tasks/source/task-to-v4.ts
53399
53565
  import crypto3 from "crypto";
53400
- import path47 from "path";
53566
+ import path48 from "path";
53401
53567
 
53402
53568
  // src/tasks/task-id.ts
53403
53569
  var VALID_TASK_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -54206,7 +54372,7 @@ function addSharedNonPromptOverrides(data, akm) {
54206
54372
  }
54207
54373
  function promptSourceKind(raw) {
54208
54374
  const trimmed = raw.trim();
54209
- if (trimmed.startsWith("./") || trimmed.startsWith("../") || path47.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54375
+ if (trimmed.startsWith("./") || trimmed.startsWith("../") || path48.isAbsolute(trimmed) || /^[A-Za-z]:[\\/]/.test(trimmed)) {
54210
54376
  return "file";
54211
54377
  }
54212
54378
  try {
@@ -54310,7 +54476,7 @@ function planV2DataToV4(input, data) {
54310
54476
  return blocked(input, "read-only-source", !input.writable ? "the owning source is not writable" : "the source file or publication directory is read-only");
54311
54477
  }
54312
54478
  try {
54313
- validateTaskId(path47.basename(input.filePath, ".yml"));
54479
+ validateTaskId(path48.basename(input.filePath, ".yml"));
54314
54480
  } catch (cause) {
54315
54481
  return blocked(input, "invalid-v2-task", causeMessage(cause));
54316
54482
  }
@@ -54455,7 +54621,7 @@ function taskToV4PlanFromOutcomes(outcomes) {
54455
54621
  for (let index = 1;index < files.length; index += 1) {
54456
54622
  const previous = files[index - 1];
54457
54623
  const current = files[index];
54458
- if (previous && current && path47.resolve(previous.filePath) === path47.resolve(current.filePath)) {
54624
+ if (previous && current && path48.resolve(previous.filePath) === path48.resolve(current.filePath)) {
54459
54625
  throw new Error(`duplicate task migration file path: ${current.filePath}`);
54460
54626
  }
54461
54627
  }
@@ -54467,18 +54633,18 @@ function migrationError(detail) {
54467
54633
  return new ConfigError(`Task migration failed: ${detail}`, "INVALID_CONFIG_FILE");
54468
54634
  }
54469
54635
  function contained2(root2, candidate) {
54470
- const relative = path48.relative(root2, candidate);
54471
- return relative === "" || !relative.startsWith("..") && !path48.isAbsolute(relative);
54636
+ const relative = path49.relative(root2, candidate);
54637
+ return relative === "" || !relative.startsWith("..") && !path49.isAbsolute(relative);
54472
54638
  }
54473
54639
  function realDirectory(filePath) {
54474
- const stat = fs39.lstatSync(filePath);
54640
+ const stat = fs40.lstatSync(filePath);
54475
54641
  if (stat.isSymbolicLink() || !stat.isDirectory())
54476
54642
  throw migrationError(`${filePath} must be a real directory.`);
54477
- return fs39.realpathSync(filePath);
54643
+ return fs40.realpathSync(filePath);
54478
54644
  }
54479
54645
  function isWritable(filePath) {
54480
54646
  try {
54481
- fs39.accessSync(filePath, fs39.constants.W_OK);
54647
+ fs40.accessSync(filePath, fs40.constants.W_OK);
54482
54648
  return true;
54483
54649
  } catch {
54484
54650
  return false;
@@ -54491,12 +54657,12 @@ function walkTasks(root2, tasksDir, out) {
54491
54657
  throw migrationError(`${root2.root} resolves outside bundle ${root2.bundleId}.`);
54492
54658
  }
54493
54659
  const visit2 = (directory) => {
54494
- const physicalDirectory = fs39.realpathSync(directory);
54660
+ const physicalDirectory = fs40.realpathSync(directory);
54495
54661
  if (!contained2(physicalRoot, physicalDirectory)) {
54496
54662
  throw migrationError(`${directory} resolves outside bundle ${root2.bundleId}.`);
54497
54663
  }
54498
- for (const entry of fs39.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54499
- const candidate = path48.join(directory, entry.name);
54664
+ for (const entry of fs40.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
54665
+ const candidate = path49.join(directory, entry.name);
54500
54666
  if (entry.isSymbolicLink())
54501
54667
  throw migrationError(`task migration does not follow symbolic link ${candidate}.`);
54502
54668
  if (entry.isDirectory()) {
@@ -54505,11 +54671,11 @@ function walkTasks(root2, tasksDir, out) {
54505
54671
  }
54506
54672
  if (!entry.isFile() || !entry.name.endsWith(".yml"))
54507
54673
  continue;
54508
- const stat = fs39.lstatSync(candidate);
54674
+ const stat = fs40.lstatSync(candidate);
54509
54675
  const mode = stat.mode & 511;
54510
54676
  out.push({
54511
54677
  filePath: candidate,
54512
- bytes: fs39.readFileSync(candidate),
54678
+ bytes: fs40.readFileSync(candidate),
54513
54679
  mode,
54514
54680
  writable: root2.writable,
54515
54681
  onDiskWritable: isWritable(candidate) && isWritable(directory) && (mode & 146) !== 0,
@@ -54522,9 +54688,9 @@ function walkTasks(root2, tasksDir, out) {
54522
54688
  function inspectTaskFiles(roots) {
54523
54689
  const files = [];
54524
54690
  for (const root2 of [...roots].sort((a, b) => a.bundleId.localeCompare(b.bundleId))) {
54525
- const tasksDir = root2.layout === "akm-task" ? root2.root : path48.join(root2.root, "tasks");
54691
+ const tasksDir = root2.layout === "akm-task" ? root2.root : path49.join(root2.root, "tasks");
54526
54692
  try {
54527
- const stat = fs39.lstatSync(tasksDir);
54693
+ const stat = fs40.lstatSync(tasksDir);
54528
54694
  if (stat.isSymbolicLink())
54529
54695
  throw migrationError(`task migration does not follow symbolic link ${tasksDir}.`);
54530
54696
  if (!stat.isDirectory())
@@ -54542,18 +54708,18 @@ function planTaskFilesMigration(inputs) {
54542
54708
  return taskToV4PlanFromOutcomes(inputs.map(planTaskToV4File));
54543
54709
  }
54544
54710
  function taskFileBackupPath(backupRoot, filePath) {
54545
- const digest = crypto4.createHash("sha256").update(path48.resolve(filePath)).digest("hex").slice(0, 16);
54546
- return path48.join(backupRoot, "files", `${digest}-${path48.basename(filePath)}`);
54711
+ const digest = crypto4.createHash("sha256").update(path49.resolve(filePath)).digest("hex").slice(0, 16);
54712
+ return path49.join(backupRoot, "files", `${digest}-${path49.basename(filePath)}`);
54547
54713
  }
54548
54714
  function fsyncDirectory(directory) {
54549
54715
  if (process.platform === "win32")
54550
54716
  return;
54551
54717
  try {
54552
- const fd = fs39.openSync(directory, "r");
54718
+ const fd = fs40.openSync(directory, "r");
54553
54719
  try {
54554
- fs39.fsyncSync(fd);
54720
+ fs40.fsyncSync(fd);
54555
54721
  } finally {
54556
- fs39.closeSync(fd);
54722
+ fs40.closeSync(fd);
54557
54723
  }
54558
54724
  } catch (cause) {
54559
54725
  const code = cause.code;
@@ -54562,25 +54728,25 @@ function fsyncDirectory(directory) {
54562
54728
  }
54563
54729
  }
54564
54730
  function writeDurable(filePath, bytes, mode, exclusive = false) {
54565
- fs39.mkdirSync(path48.dirname(filePath), { recursive: true });
54566
- const fd = fs39.openSync(filePath, exclusive ? "wx" : "w", mode);
54731
+ fs40.mkdirSync(path49.dirname(filePath), { recursive: true });
54732
+ const fd = fs40.openSync(filePath, exclusive ? "wx" : "w", mode);
54567
54733
  try {
54568
- fs39.writeFileSync(fd, bytes);
54569
- fs39.fsyncSync(fd);
54734
+ fs40.writeFileSync(fd, bytes);
54735
+ fs40.fsyncSync(fd);
54570
54736
  } finally {
54571
- fs39.closeSync(fd);
54737
+ fs40.closeSync(fd);
54572
54738
  }
54573
- fs39.chmodSync(filePath, mode);
54574
- fsyncDirectory(path48.dirname(filePath));
54739
+ fs40.chmodSync(filePath, mode);
54740
+ fsyncDirectory(path49.dirname(filePath));
54575
54741
  }
54576
54742
  function replaceAtomically(filePath, bytes, mode) {
54577
- const temporary = path48.join(path48.dirname(filePath), `.${path48.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54743
+ const temporary = path49.join(path49.dirname(filePath), `.${path49.basename(filePath)}.migrate-${crypto4.randomUUID()}`);
54578
54744
  try {
54579
54745
  writeDurable(temporary, bytes, mode, true);
54580
- fs39.renameSync(temporary, filePath);
54581
- fsyncDirectory(path48.dirname(filePath));
54746
+ fs40.renameSync(temporary, filePath);
54747
+ fsyncDirectory(path49.dirname(filePath));
54582
54748
  } finally {
54583
- fs39.rmSync(temporary, { force: true });
54749
+ fs40.rmSync(temporary, { force: true });
54584
54750
  }
54585
54751
  }
54586
54752
  function applyTaskFilesPlan(plan, options) {
@@ -54603,7 +54769,7 @@ function applyTaskFilesPlan(plan, options) {
54603
54769
  }
54604
54770
  } catch (cause) {
54605
54771
  for (const change of [...replaced].reverse()) {
54606
- replaceAtomically(change.filePath, fs39.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54772
+ replaceAtomically(change.filePath, fs40.readFileSync(taskFileBackupPath(options.backupRoot, change.filePath)), change.mode);
54607
54773
  }
54608
54774
  throw cause;
54609
54775
  }
@@ -54613,14 +54779,14 @@ function applyTaskFilesPlan(plan, options) {
54613
54779
  // scripts/akm-migrate/task-migrate.ts
54614
54780
  function expandTilde(value) {
54615
54781
  if (value === "~")
54616
- return os7.homedir();
54782
+ return os8.homedir();
54617
54783
  if (value.startsWith("~/") || value.startsWith("~\\"))
54618
- return path49.join(os7.homedir(), value.slice(2));
54784
+ return path50.join(os8.homedir(), value.slice(2));
54619
54785
  return value;
54620
54786
  }
54621
54787
  function existingDirectory(target) {
54622
54788
  try {
54623
- return fs40.statSync(target).isDirectory();
54789
+ return fs41.statSync(target).isDirectory();
54624
54790
  } catch (cause) {
54625
54791
  if (cause.code === "ENOENT")
54626
54792
  return false;
@@ -54641,14 +54807,14 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54641
54807
  const source = sources.get(bundleId);
54642
54808
  if (!source)
54643
54809
  continue;
54644
- const configuredRoot = source.type === "filesystem" && source.path ? path49.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54810
+ const configuredRoot = source.type === "filesystem" && source.path ? path50.resolve(resolutionBase, expandTilde(source.path)) : lockContentRootFor(bundleId, source.type);
54645
54811
  if (!configuredRoot || !existingDirectory(configuredRoot))
54646
54812
  continue;
54647
- const bundleRoot = path49.resolve(configuredRoot);
54813
+ const bundleRoot = path50.resolve(configuredRoot);
54648
54814
  const component = bundleComponentConfig(bundle);
54649
- const componentRoot = path49.resolve(bundleRoot, component?.root ?? ".");
54650
- const relative = path49.relative(bundleRoot, componentRoot);
54651
- if (relative === ".." || relative.startsWith(`..${path49.sep}`) || path49.isAbsolute(relative)) {
54815
+ const componentRoot = path50.resolve(bundleRoot, component?.root ?? ".");
54816
+ const relative = path50.relative(bundleRoot, componentRoot);
54817
+ if (relative === ".." || relative.startsWith(`..${path50.sep}`) || path50.isAbsolute(relative)) {
54652
54818
  throw new ConfigError(`Task migration component root ${componentRoot} escapes bundle ${bundleId} at ${bundleRoot}.`, "INVALID_CONFIG_FILE");
54653
54819
  }
54654
54820
  if (!existingDirectory(componentRoot))
@@ -54665,7 +54831,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54665
54831
  }
54666
54832
  const envStash = process.env.AKM_BUNDLE_DIR?.trim();
54667
54833
  if (envStash && existingDirectory(envStash)) {
54668
- const stashRoot = path49.resolve(envStash);
54834
+ const stashRoot = path50.resolve(envStash);
54669
54835
  if (!rootsByPath.has(stashRoot)) {
54670
54836
  const bundleId = deriveBundleId(undefined, stashRoot, new Set(Object.keys(config.bundles ?? {})));
54671
54837
  const candidate = taskRoot(bundleId, stashRoot, stashRoot, detectAdapterId(stashRoot), () => true);
@@ -54678,7 +54844,7 @@ function taskRoots(config, resolutionBase = process.cwd()) {
54678
54844
  function taskRoot(bundleId, bundleRoot, componentRoot, configuredAdapter, writable) {
54679
54845
  const adapter = configuredAdapter ?? detectAdapterId(componentRoot, "");
54680
54846
  if (!configuredAdapter && adapter === "") {
54681
- const flatTasks = fs40.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54847
+ const flatTasks = fs41.readdirSync(componentRoot, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".yml")).map((entry) => entry.name).sort();
54682
54848
  if (flatTasks.length > 0) {
54683
54849
  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");
54684
54850
  }
@@ -54734,7 +54900,7 @@ function applyTaskFilesMigration() {
54734
54900
  const before = inspectCurrent();
54735
54901
  if (before.result.taskFiles.changed === 0)
54736
54902
  return before.result;
54737
- const backupPath = path49.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54903
+ const backupPath = path50.join(getDataDir(), "backups", "tasks", `${Date.now()}-${randomUUID3()}`);
54738
54904
  const applied = applyTaskFilesPlan(before.plan, { backupRoot: backupPath });
54739
54905
  return { ...inspectCurrent().result, backupPath, applied: applied.changed.length };
54740
54906
  });