overlane 0.1.112 → 0.1.114

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/overlane.mjs CHANGED
@@ -21308,6 +21308,74 @@ var init_identity = __esm({
21308
21308
  }
21309
21309
  });
21310
21310
 
21311
+ // ../contracts/src/task-priority.ts
21312
+ var TASK_PRIORITIES, TaskPriority, TASK_ORIGINS, TaskOrigin, taskQueuePaths, RequestId2, PrioritiseRequest, PrioritiseResult, QueueEntry, TaskQueue, NextTask, TASK_ENFORCEMENT, TaskEnforcement, TaskPolicy, SetTaskPolicyRequest;
21313
+ var init_task_priority = __esm({
21314
+ "../contracts/src/task-priority.ts"() {
21315
+ "use strict";
21316
+ init_zod();
21317
+ init_common();
21318
+ init_executor();
21319
+ init_task_api();
21320
+ init_task_contract();
21321
+ TASK_PRIORITIES = ["P0", "P1", "P2", "P3"];
21322
+ TaskPriority = external_exports.enum(TASK_PRIORITIES);
21323
+ TASK_ORIGINS = ["user", "plan", "agent", "system"];
21324
+ TaskOrigin = external_exports.enum(TASK_ORIGINS);
21325
+ taskQueuePaths = {
21326
+ base: (tenantId, projectId) => `/v1/tenants/${encodeURIComponent(tenantId)}/projects/${encodeURIComponent(projectId)}/queue`,
21327
+ next: (tenantId, projectId) => `${taskQueuePaths.base(tenantId, projectId)}/next`,
21328
+ policy: (tenantId, projectId) => `${taskQueuePaths.base(tenantId, projectId)}/policy`,
21329
+ prioritise: (tenantId, projectId, taskId) => `${taskQueuePaths.base(tenantId, projectId)}/${encodeURIComponent(taskId)}/prioritise`
21330
+ };
21331
+ RequestId2 = external_exports.string().min(8).max(128);
21332
+ PrioritiseRequest = external_exports.object({
21333
+ requestId: RequestId2,
21334
+ priority: TaskPriority,
21335
+ top: external_exports.boolean().default(false),
21336
+ /** Who asked for the work; recorded the first time a task is ranked. */
21337
+ origin: TaskOrigin.default("agent"),
21338
+ reason: external_exports.string().min(1).max(300).optional(),
21339
+ /** The task this one displaces; the ledger records `task.preempted`. */
21340
+ preempts: TaskId.optional(),
21341
+ executor: Executor
21342
+ }).strict();
21343
+ PrioritiseResult = external_exports.object({
21344
+ taskId: TaskId,
21345
+ priority: TaskPriority,
21346
+ rank: external_exports.number().int(),
21347
+ origin: TaskOrigin,
21348
+ previous: external_exports.object({ priority: TaskPriority, rank: external_exports.number().int() }).strict().nullable(),
21349
+ changed: external_exports.boolean()
21350
+ }).strict();
21351
+ QueueEntry = external_exports.object({
21352
+ taskId: TaskId,
21353
+ title: external_exports.string(),
21354
+ state: TaskState,
21355
+ pauseReason: PauseReason.optional(),
21356
+ priority: TaskPriority,
21357
+ rank: external_exports.number().int(),
21358
+ origin: TaskOrigin,
21359
+ version: external_exports.number().int().positive()
21360
+ }).strict();
21361
+ TaskQueue = external_exports.object({ tasks: external_exports.array(QueueEntry) }).strict();
21362
+ NextTask = external_exports.object({
21363
+ task: QueueEntry.nullable(),
21364
+ preempt: external_exports.boolean(),
21365
+ why: external_exports.string()
21366
+ }).strict();
21367
+ TASK_ENFORCEMENT = ["required", "relaxed"];
21368
+ TaskEnforcement = external_exports.enum(TASK_ENFORCEMENT);
21369
+ TaskPolicy = external_exports.object({
21370
+ enforcement: TaskEnforcement,
21371
+ reason: external_exports.string().optional(),
21372
+ changedBy: external_exports.string().optional(),
21373
+ updatedAt: Timestamp.optional()
21374
+ }).strict();
21375
+ SetTaskPolicyRequest = external_exports.object({ requestId: RequestId2, enforcement: TaskEnforcement, reason: external_exports.string().min(1).max(300).optional(), executor: Executor }).strict().refine((request) => request.enforcement === "required" || request.reason !== void 0, { message: "relaxing the task requirement needs a reason", path: ["reason"] });
21376
+ }
21377
+ });
21378
+
21311
21379
  // ../contracts/src/index.ts
21312
21380
  var init_src = __esm({
21313
21381
  "../contracts/src/index.ts"() {
@@ -21325,6 +21393,7 @@ var init_src = __esm({
21325
21393
  init_release();
21326
21394
  init_kit();
21327
21395
  init_identity();
21396
+ init_task_priority();
21328
21397
  }
21329
21398
  });
21330
21399
 
@@ -28659,7 +28728,7 @@ var require_dist = __commonJS({
28659
28728
  });
28660
28729
 
28661
28730
  // src/assets.ts
28662
- import { basename as basename3, join as join21, resolve as resolve6 } from "node:path";
28731
+ import { basename as basename3, join as join22, resolve as resolve6 } from "node:path";
28663
28732
  import { fileURLToPath } from "node:url";
28664
28733
  function packageRoot(env = process.env) {
28665
28734
  const override = env["MVRX_PACKAGE_ROOT"];
@@ -28668,16 +28737,16 @@ function packageRoot(env = process.env) {
28668
28737
  }
28669
28738
  function assetDir(env = process.env) {
28670
28739
  const override = env["MVRX_ASSET_DIR"];
28671
- return override !== void 0 && override !== "" ? override : join21(packageRoot(env), "assets");
28740
+ return override !== void 0 && override !== "" ? override : join22(packageRoot(env), "assets");
28672
28741
  }
28673
28742
  function assetFile(name2) {
28674
- return join21(assetDir(), basename3(name2));
28743
+ return join22(assetDir(), basename3(name2));
28675
28744
  }
28676
28745
  var VERSION;
28677
28746
  var init_assets = __esm({
28678
28747
  "src/assets.ts"() {
28679
28748
  "use strict";
28680
- VERSION = true ? "0.1.112" : "0.0.0-dev";
28749
+ VERSION = true ? "0.1.114" : "0.0.0-dev";
28681
28750
  }
28682
28751
  });
28683
28752
 
@@ -36606,7 +36675,7 @@ var init_treesitter = __esm({
36606
36675
  import { execFile } from "node:child_process";
36607
36676
  import { createHash as createHash6 } from "node:crypto";
36608
36677
  import { lstat, readFile as readFile4 } from "node:fs/promises";
36609
- import { join as join22 } from "node:path";
36678
+ import { join as join23 } from "node:path";
36610
36679
  import { promisify } from "node:util";
36611
36680
  function shardKeyOf(shard) {
36612
36681
  return `sha256:${sha256Hex(Buffer.from(`${shard.path}\0${shard.contentHash}\0${shard.precision}`, "utf8"))}`;
@@ -36633,7 +36702,7 @@ async function mapLimit(items, limit, task) {
36633
36702
  return results;
36634
36703
  }
36635
36704
  async function hashRegularFile(repoRoot, path) {
36636
- const absolute = join22(repoRoot, path);
36705
+ const absolute = join23(repoRoot, path);
36637
36706
  try {
36638
36707
  const stats = await lstat(absolute);
36639
36708
  if (!stats.isFile()) return null;
@@ -36671,7 +36740,7 @@ async function buildSnapshot(options) {
36671
36740
  const needParse = [...hashes.keys()].filter((path) => !byPath.has(path));
36672
36741
  const parsed = await mapLimit(needParse, 8, async (path) => {
36673
36742
  if (languageForPath(path) === null) return { path, shard: null };
36674
- const bytes = await readFile4(join22(options.repoRoot, path));
36743
+ const bytes = await readFile4(join23(options.repoRoot, path));
36675
36744
  if (bytes.byteLength > MAX_PARSE_BYTES) return { path, shard: null };
36676
36745
  const hash2 = `sha256:${sha256Hex(bytes)}`;
36677
36746
  if (hash2 !== hashes.get(path)) throw new Error(`${path} changed while the snapshot was being built`);
@@ -36814,7 +36883,7 @@ var init_oidc = __esm({
36814
36883
  // ../index-builder/src/run.ts
36815
36884
  import { execFile as execFile2 } from "node:child_process";
36816
36885
  import { mkdir as mkdir3, readdir as readdir4, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
36817
- import { join as join23, resolve as resolve7 } from "node:path";
36886
+ import { join as join24, resolve as resolve7 } from "node:path";
36818
36887
  import { parseArgs as parseArgs2 } from "node:util";
36819
36888
  import { promisify as promisify2 } from "node:util";
36820
36889
  async function git3(root, args2) {
@@ -36886,13 +36955,13 @@ ${USAGE}`);
36886
36955
  }
36887
36956
  }
36888
36957
  async function writeSnapshot(dir, built) {
36889
- await mkdir3(join23(dir, "shards"), { recursive: true });
36890
- for (const name2 of await readdir4(join23(dir, "shards"))) await rm2(join23(dir, "shards", name2));
36891
- await writeFile3(join23(dir, "manifest.json"), JSON.stringify(built.manifest, null, 2));
36892
- await writeFile3(join23(dir, "uncovered.json"), JSON.stringify(built.uncovered, null, 2));
36958
+ await mkdir3(join24(dir, "shards"), { recursive: true });
36959
+ for (const name2 of await readdir4(join24(dir, "shards"))) await rm2(join24(dir, "shards", name2));
36960
+ await writeFile3(join24(dir, "manifest.json"), JSON.stringify(built.manifest, null, 2));
36961
+ await writeFile3(join24(dir, "uncovered.json"), JSON.stringify(built.uncovered, null, 2));
36893
36962
  for (const shard of built.shards) {
36894
36963
  const name2 = shardKeyOf(shard).slice("sha256:".length);
36895
- await writeFile3(join23(dir, "shards", `${name2}.json`), JSON.stringify(shard));
36964
+ await writeFile3(join24(dir, "shards", `${name2}.json`), JSON.stringify(shard));
36896
36965
  }
36897
36966
  }
36898
36967
  var execFileAsync2, USAGE, UsageError2, OPTIONS;
@@ -51730,7 +51799,7 @@ var init_cloud = __esm({
51730
51799
  // ../code-shim/src/git.ts
51731
51800
  import { execFileSync } from "node:child_process";
51732
51801
  import { existsSync as existsSync6 } from "node:fs";
51733
- import { join as join27 } from "node:path";
51802
+ import { join as join28 } from "node:path";
51734
51803
  function git4(root, args2) {
51735
51804
  try {
51736
51805
  return execFileSync("git", args2, { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 64 * 1024 * 1024, timeout: 1e4 });
@@ -51792,7 +51861,7 @@ function readWorkingCopyState(root) {
51792
51861
  const head = headCommit2(root);
51793
51862
  const raw = git4(root, ["status", "--porcelain=v2", "-z", "--untracked-files=all"]);
51794
51863
  if (raw === null) return { head, dirty: /* @__PURE__ */ new Set(), deleted: /* @__PURE__ */ new Set(), renamed: /* @__PURE__ */ new Map() };
51795
- return { head, ...parseStatus(raw, (path) => existsSync6(join27(root, path))) };
51864
+ return { head, ...parseStatus(raw, (path) => existsSync6(join28(root, path))) };
51796
51865
  }
51797
51866
  var init_git = __esm({
51798
51867
  "../code-shim/src/git.ts"() {
@@ -51803,16 +51872,16 @@ var init_git = __esm({
51803
51872
  // ../code-shim/src/config.ts
51804
51873
  import { readFileSync as readFileSync7 } from "node:fs";
51805
51874
  import { homedir as homedir2 } from "node:os";
51806
- import { join as join28 } from "node:path";
51875
+ import { join as join29 } from "node:path";
51807
51876
  function configDir(env) {
51808
- const base2 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join28(homedir2(), ".config");
51809
- return join28(base2, "mvrx-harness");
51877
+ const base2 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join29(homedir2(), ".config");
51878
+ return join29(base2, "mvrx-harness");
51810
51879
  }
51811
51880
  function findToken2(env, serviceUrl, now) {
51812
51881
  const fromEnv = env["HARNESS_TOKEN"];
51813
51882
  if (fromEnv !== void 0 && fromEnv.length > 0) return fromEnv;
51814
51883
  try {
51815
- const file2 = JSON.parse(readFileSync7(join28(configDir(env), "credentials.json"), "utf8"));
51884
+ const file2 = JSON.parse(readFileSync7(join29(configDir(env), "credentials.json"), "utf8"));
51816
51885
  const stored = file2[serviceUrl];
51817
51886
  if (stored === void 0 || typeof stored.accessToken !== "string" || stored.accessToken.length === 0) return null;
51818
51887
  if (typeof stored.expiresAt === "number" && stored.expiresAt <= now) return null;
@@ -51824,7 +51893,7 @@ function findToken2(env, serviceUrl, now) {
51824
51893
  function resolveCloudConfig(root, env, now) {
51825
51894
  let binding;
51826
51895
  try {
51827
- const parsed = ProjectBinding.safeParse(JSON.parse(readFileSync7(join28(root, ".harness", "project.json"), "utf8")));
51896
+ const parsed = ProjectBinding.safeParse(JSON.parse(readFileSync7(join29(root, ".harness", "project.json"), "utf8")));
51828
51897
  if (!parsed.success) return null;
51829
51898
  binding = parsed.data;
51830
51899
  } catch {
@@ -52215,7 +52284,7 @@ var init_nav = __esm({
52215
52284
 
52216
52285
  // ../code-shim/src/edit.ts
52217
52286
  import { createHash as createHash8 } from "node:crypto";
52218
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
52287
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "node:fs";
52219
52288
  function lineStarts(text) {
52220
52289
  const starts = [0];
52221
52290
  for (let i2 = 0; i2 < text.length; i2 += 1) if (text[i2] === "\n") starts.push(i2 + 1);
@@ -52284,7 +52353,7 @@ ${args2.content.replace(/\n+$/, "")}`;
52284
52353
  const before = positionAt(next, changedStart);
52285
52354
  const after = positionAt(next, insertAt + inserted.length);
52286
52355
  const bytes = Buffer.from(next, "utf8");
52287
- writeFileSync7(absolute, bytes);
52356
+ writeFileSync8(absolute, bytes);
52288
52357
  return {
52289
52358
  ok: true,
52290
52359
  path: args2.path,
@@ -52345,7 +52414,7 @@ async function renameSymbol(deps, args2) {
52345
52414
  let next = item.text;
52346
52415
  for (const offset of offsets) next = next.slice(0, offset) + args2.new_name + next.slice(offset + oldName.length);
52347
52416
  const bytes = Buffer.from(next, "utf8");
52348
- writeFileSync7(item.absolute, bytes);
52417
+ writeFileSync8(item.absolute, bytes);
52349
52418
  filesChanged.push({ path: item.path, edits: offsets.length, sha256: sha2563(bytes) });
52350
52419
  edits += offsets.length;
52351
52420
  }
@@ -58229,6 +58298,239 @@ var runResumeCommand = defineCommand({
58229
58298
  });
58230
58299
  var runCommands = [runStartCommand, runNextCommand, runClaimCommand, runDecideCommand, runEndCommand, runStatusCommand, runPauseCommand, runResumeCommand];
58231
58300
 
58301
+ // ../cli/src/task/queue.ts
58302
+ init_src();
58303
+ init_zod();
58304
+ import { randomUUID as randomUUID4 } from "node:crypto";
58305
+ import { mkdirSync as mkdirSync7, renameSync as renameSync5, writeFileSync as writeFileSync6 } from "node:fs";
58306
+ import { dirname as dirname7, join as join21 } from "node:path";
58307
+ var TASK_POLICY_PATH = join21(".harness", "task-policy.json");
58308
+ function writePolicyFile(root, policy, nowMs) {
58309
+ const path = join21(root, TASK_POLICY_PATH);
58310
+ mkdirSync7(dirname7(path), { recursive: true });
58311
+ const temp = `${path}.${process.pid}.tmp`;
58312
+ writeFileSync6(temp, `${JSON.stringify({ enforcement: policy.enforcement, ...policy.reason === void 0 ? {} : { reason: policy.reason }, checkedAt: new Date(nowMs).toISOString() }, null, 2)}
58313
+ `);
58314
+ renameSync5(temp, path);
58315
+ }
58316
+ var TaskNewResult = withDryRun(
58317
+ external_exports.object({ taskId: external_exports.string(), version: external_exports.number(), state: external_exports.string(), holder: external_exports.string(), priority: TaskPriority, rank: external_exports.number(), next: external_exports.string() })
58318
+ );
58319
+ var TaskNextResult = external_exports.object({ task: NextTask.shape.task, preempt: external_exports.boolean(), why: external_exports.string(), command: external_exports.string().nullable() });
58320
+ var TaskQueueResult = TaskQueue;
58321
+ var TaskPrioritiseResult = withDryRun(external_exports.object({ ...PrioritiseResult.shape, next: external_exports.string() }));
58322
+ var TaskPolicyResult = external_exports.object({ enforcement: TaskEnforcement, reason: external_exports.string().optional(), changedBy: external_exports.string().optional(), updatedAt: external_exports.string().optional(), localFile: external_exports.string() });
58323
+ var TaskPolicySetResult = withDryRun(TaskPolicyResult);
58324
+ var requestId3 = () => `cli-${randomUUID4()}`;
58325
+ function priorityOf(value, fallback) {
58326
+ const parsed = TaskPriority.safeParse(value ?? fallback);
58327
+ if (!parsed.success) throw new UsageError(`--priority must be one of ${TASK_PRIORITIES.join(", ")}`);
58328
+ return parsed.data;
58329
+ }
58330
+ var mcpExecutor = (name2) => name2 === "codex" ? "codex" : "claude-code";
58331
+ var commandFor = (entry) => `overlane task ${entry.state === "paused" ? "resume" : "start"} ${entry.taskId}`;
58332
+ async function taskNext(deps) {
58333
+ const project = await connectedProject(deps, "task");
58334
+ const call2 = serviceCall(deps, project.serviceUrl, project.token);
58335
+ const current2 = readTaskState(project.root)?.taskId;
58336
+ const query = `?executor=${mcpExecutor(detectExecutorName(deps.env))}${current2 === void 0 ? "" : `&current=${encodeURIComponent(current2)}`}`;
58337
+ const next = await call2(NextTask, "GET", `${taskQueuePaths.next(project.binding.tenantId, project.binding.projectId)}${query}`);
58338
+ if (next.task === null) {
58339
+ say(deps, 'Nothing is ready or paused. Create work with `overlane task new "<title>"`.');
58340
+ return { data: { ...next, command: null } };
58341
+ }
58342
+ const command = commandFor(next.task);
58343
+ say(deps, `Next: ${next.task.taskId} (${next.task.priority}, ${next.task.state}) ${next.task.title}`);
58344
+ say(deps, next.why);
58345
+ if (next.preempt) say(deps, `This outranks your current task ${current2 ?? ""}: checkpoint it (\`overlane task checkpoint --summary "..." --next "..." --pause user\`), then run: ${command}`);
58346
+ else say(deps, `Run: ${command}`);
58347
+ return { data: { ...next, command } };
58348
+ }
58349
+ async function taskQueue(deps) {
58350
+ const project = await connectedProject(deps, "task");
58351
+ const queue = await serviceCall(deps, project.serviceUrl, project.token)(TaskQueue, "GET", taskQueuePaths.base(project.binding.tenantId, project.binding.projectId));
58352
+ if (queue.tasks.length === 0) say(deps, "The queue is empty.");
58353
+ for (const entry of queue.tasks) say(deps, `${entry.priority} ${entry.taskId} ${entry.state}${entry.pauseReason === void 0 ? "" : `/${entry.pauseReason}`} ${entry.title}`);
58354
+ return { data: queue };
58355
+ }
58356
+ async function prioritiseTask(deps, input2) {
58357
+ if (input2.taskId === void 0) throw new UsageError("prioritise needs exactly one TASK_ID");
58358
+ if (input2.priority === void 0) throw new UsageError("prioritise needs --priority P0|P1|P2|P3");
58359
+ const priority = priorityOf(input2.priority, void 0);
58360
+ const name2 = detectExecutorName(deps.env);
58361
+ let request;
58362
+ try {
58363
+ request = PrioritiseRequest.parse({ requestId: requestId3(), priority, top: input2.top, origin: name2 === "terminal" ? "user" : "agent", ...input2.reason === void 0 ? {} : { reason: input2.reason }, executor: executorFor(name2) });
58364
+ } catch (error62) {
58365
+ throw new UsageError(String(error62));
58366
+ }
58367
+ if (input2.dryRun) {
58368
+ const project2 = await offlineProject(deps, "task");
58369
+ return planOutcome(deps, dryRunPlan({ service: project2.serviceUrl, requests: [{ method: "POST", path: taskQueuePaths.prioritise(project2.binding.tenantId, project2.binding.projectId, input2.taskId), body: request }] }));
58370
+ }
58371
+ const project = await connectedProject(deps, "task");
58372
+ const result = await serviceCall(deps, project.serviceUrl, project.token)(PrioritiseResult, "POST", taskQueuePaths.prioritise(project.binding.tenantId, project.binding.projectId, input2.taskId), request);
58373
+ say(deps, `${result.taskId} is now ${result.priority}${input2.top ? " and first in its priority" : ""} (rank ${result.rank}).${result.changed ? "" : " Nothing changed."}`);
58374
+ return { data: { ...result, next: "overlane task next" } };
58375
+ }
58376
+ async function newTask(deps, input2) {
58377
+ const title = input2.title.replace(/\s+/g, " ").trim();
58378
+ if (title.length === 0) throw new UsageError('new needs a title: overlane task new "<title>"');
58379
+ const priority = priorityOf(input2.priority, "P1");
58380
+ const started = await startTask(deps, {
58381
+ outcome: title,
58382
+ criteria: input2.criteria.length > 0 ? input2.criteria : [`Complete: ${title}`],
58383
+ paths: input2.paths.length > 0 ? input2.paths : ["**"],
58384
+ checks: input2.checks,
58385
+ dryRun: input2.dryRun
58386
+ });
58387
+ const data = started?.data;
58388
+ if (data === void 0 || "dryRun" in data) return started;
58389
+ const begun = data;
58390
+ const project = await connectedProject(deps, "task");
58391
+ const name2 = detectExecutorName(deps.env);
58392
+ const request = PrioritiseRequest.parse({ requestId: requestId3(), priority, top: input2.top, origin: name2 === "terminal" ? "user" : "agent", executor: executorFor(name2) });
58393
+ try {
58394
+ const ranked = await serviceCall(deps, project.serviceUrl, project.token)(PrioritiseResult, "POST", taskQueuePaths.prioritise(project.binding.tenantId, project.binding.projectId, begun.taskId), request);
58395
+ say(deps, `Ranked ${begun.taskId} ${ranked.priority}${input2.top ? " (first)" : ""}.`);
58396
+ return { data: { taskId: begun.taskId, version: begun.version, state: begun.state, holder: begun.holder, priority: ranked.priority, rank: ranked.rank, next: begun.next } };
58397
+ } catch (error62) {
58398
+ warn(deps, `task ${begun.taskId} is claimed but could not be ranked (${error62 instanceof Error ? error62.message : String(error62)}); run \`overlane task prioritise ${begun.taskId} --priority ${priority}\``);
58399
+ return { data: { taskId: begun.taskId, version: begun.version, state: begun.state, holder: begun.holder, priority: "P1", rank: 0, next: begun.next } };
58400
+ }
58401
+ }
58402
+ async function showPolicy2(deps) {
58403
+ const project = await connectedProject(deps, "task");
58404
+ const policy = await serviceCall(deps, project.serviceUrl, project.token)(TaskPolicy, "GET", taskQueuePaths.policy(project.binding.tenantId, project.binding.projectId));
58405
+ writePolicyFile(project.root, policy, deps.now());
58406
+ say(deps, `Task requirement: ${policy.enforcement}${policy.reason === void 0 ? "" : ` (${policy.reason})`}.`);
58407
+ return { data: { ...policy, localFile: TASK_POLICY_PATH } };
58408
+ }
58409
+ async function setPolicy(deps, input2) {
58410
+ const enforcement = TaskEnforcement.safeParse(input2.enforcement);
58411
+ if (!enforcement.success) throw new UsageError(`set needs ${TASK_ENFORCEMENT.join(" or ")}`);
58412
+ const name2 = detectExecutorName(deps.env);
58413
+ const parsed = SetTaskPolicyRequest.safeParse({ requestId: requestId3(), enforcement: enforcement.data, ...input2.reason === void 0 ? {} : { reason: input2.reason }, executor: executorFor(name2) });
58414
+ if (!parsed.success) throw new UsageError(parsed.error.issues.map((issue2) => issue2.message).join("; "));
58415
+ if (input2.dryRun) {
58416
+ const project2 = await offlineProject(deps, "task");
58417
+ return planOutcome(
58418
+ deps,
58419
+ dryRunPlan({
58420
+ service: project2.serviceUrl,
58421
+ requests: [{ method: "PUT", path: taskQueuePaths.policy(project2.binding.tenantId, project2.binding.projectId), body: parsed.data, note: "only a signed-in owner or admin may change it" }],
58422
+ writes: [{ path: TASK_POLICY_PATH, action: "write", description: "this working copy's copy of the requirement (never committed)" }]
58423
+ })
58424
+ );
58425
+ }
58426
+ const project = await connectedProject(deps, "task");
58427
+ const policy = await serviceCall(deps, project.serviceUrl, project.token)(TaskPolicy, "PUT", taskQueuePaths.policy(project.binding.tenantId, project.binding.projectId), parsed.data);
58428
+ writePolicyFile(project.root, policy, deps.now());
58429
+ say(deps, policy.enforcement === "required" ? "Every change now needs an active task." : `The task requirement is relaxed (${policy.reason ?? "no reason"}). It shows in the context packet and the event stream.`);
58430
+ return { data: { ...policy, localFile: TASK_POLICY_PATH } };
58431
+ }
58432
+ async function startExisting(deps, taskId, dryRun) {
58433
+ const resumed = await resumeTask(deps, { taskId, dryRun });
58434
+ const data = resumed?.data;
58435
+ if (data === void 0 || "dryRun" in data) return resumed;
58436
+ return { data: { taskId: data.taskId, version: data.version, state: data.task.state, holder: data.holder, ...data.task.lease === void 0 ? {} : { leaseExpiresAt: data.task.lease.expiresAt }, next: "overlane task submit" } };
58437
+ }
58438
+
58439
+ // ../cli/src/commands/queue.ts
58440
+ var common3 = { needsAuth: true, needsNetwork: true };
58441
+ var PRIORITIES = ["P0", "P1", "P2", "P3"];
58442
+ var taskNewCommand = defineCommand({
58443
+ path: ["task", "new"],
58444
+ summary: "Create a task from a title, claim it for this working copy and rank it",
58445
+ description: "The quick way to get an active task, which every change needs. Creates a task with the title as its outcome (one default criterion and every path unless you pass --criterion and --path), claims it, and ranks it (default P1). Fails with exit 5 if this working copy already holds a task.",
58446
+ args: [{ name: "title", required: true, variadic: true, description: "What the task must achieve" }],
58447
+ flags: [
58448
+ { name: "priority", type: "string", enum: PRIORITIES, default: "P1", description: "P0 is most urgent, P3 least" },
58449
+ { name: "top", type: "boolean", description: "Put the task first within its priority" },
58450
+ { name: "criterion", type: "string", multiple: true, value: "TEXT", description: "An acceptance criterion; repeat for more (default: the title)" },
58451
+ { name: "path", type: "string", multiple: true, value: "GLOB", description: "A file pattern the task may change (default: everything)" },
58452
+ { name: "check", type: "string", multiple: true, value: "ID:LEVEL", description: "A required check and its minimum evidence level, for example unit_tests:L2" }
58453
+ ],
58454
+ examples: ['overlane task new "Fix login redirect"', 'overlane task new "Hotfix the build" --priority P0 --top'],
58455
+ effect: "write",
58456
+ ...common3,
58457
+ keywords: ["new task", "create task", "no active task", "blocked no task", "start work", "need a task", "begin", "quick task"],
58458
+ result: TaskNewResult,
58459
+ handler: async (inv) => newTask(inv.deps, {
58460
+ title: inv.positionals.join(" "),
58461
+ priority: textFlag(inv, "priority"),
58462
+ top: boolFlag(inv, "top"),
58463
+ criteria: listFlag(inv, "criterion"),
58464
+ paths: listFlag(inv, "path"),
58465
+ checks: listFlag(inv, "check"),
58466
+ dryRun: inv.dryRun
58467
+ })
58468
+ });
58469
+ var taskNextCommand = defineCommand({
58470
+ path: ["task", "next"],
58471
+ summary: "Show the task to work on next, ordered by priority, then rank, then plan order",
58472
+ description: "Picks the best ready or paused task: P0 before P3, then rank, then milestone and dependency order. When this working copy holds a task and the next one outranks it, says so (preempt) and prints the commands to checkpoint and switch; the preempted task comes back through this command afterwards.",
58473
+ examples: ["overlane task next"],
58474
+ effect: "read",
58475
+ ...common3,
58476
+ keywords: ["what next", "next task", "priority", "what should i work on", "pick work", "resume after", "queue"],
58477
+ result: TaskNextResult,
58478
+ handler: async (inv) => taskNext(inv.deps)
58479
+ });
58480
+ var taskQueueCommand = defineCommand({
58481
+ path: ["task", "queue"],
58482
+ summary: "List open tasks in the order they will be worked",
58483
+ description: "Lists ready, running, paused and blocked tasks by priority, then rank, then plan order, with each task's priority.",
58484
+ examples: ["overlane task queue"],
58485
+ effect: "read",
58486
+ ...common3,
58487
+ keywords: ["priority list", "ranking", "order", "backlog", "what is queued", "p0"],
58488
+ result: TaskQueueResult,
58489
+ handler: async (inv) => taskQueue(inv.deps)
58490
+ });
58491
+ var taskPrioritiseCommand = defineCommand({
58492
+ path: ["task", "prioritise"],
58493
+ summary: "Set a task's priority (P0 to P3) and optionally put it first",
58494
+ description: "Re-ranks a task. Every change is a ledger event (`task.prioritised`). With --top the task goes first within its priority. A repeated identical call changes nothing.",
58495
+ args: [{ name: "task-id", required: true, description: "The task to re-rank" }],
58496
+ flags: [
58497
+ { name: "priority", type: "string", required: true, enum: PRIORITIES, description: "P0 is most urgent, P3 least" },
58498
+ { name: "top", type: "boolean", description: "Put the task first within its priority" },
58499
+ { name: "reason", type: "string", value: "TEXT", description: "Why; kept in the event" }
58500
+ ],
58501
+ examples: ["overlane task prioritise task-7 --priority P0 --top", 'overlane task prioritise task-9 --priority P2 --reason "user said later"'],
58502
+ effect: "write",
58503
+ ...common3,
58504
+ keywords: ["reprioritize", "reprioritise", "bump", "urgent", "move to top", "rank", "lower priority", "p0", "p1", "p2", "p3"],
58505
+ result: TaskPrioritiseResult,
58506
+ handler: async (inv) => prioritiseTask(inv.deps, { taskId: inv.positionals[0], priority: textFlag(inv, "priority"), top: boolFlag(inv, "top"), reason: textFlag(inv, "reason"), dryRun: inv.dryRun })
58507
+ });
58508
+ var taskPolicyCommand = defineCommand({
58509
+ path: ["task", "policy"],
58510
+ summary: "Show whether changes need an active task, and refresh this working copy's copy",
58511
+ description: "Reads the project's task requirement (default `required`: edits and mutating shell commands are refused without an active task) and writes it to .harness/task-policy.json for the hooks.",
58512
+ examples: ["overlane task policy"],
58513
+ effect: "read",
58514
+ ...common3,
58515
+ keywords: ["enforcement", "require task", "task gate", "relax", "blocked", "policy"],
58516
+ result: TaskPolicyResult,
58517
+ handler: async (inv) => showPolicy2(inv.deps)
58518
+ });
58519
+ var taskPolicySetCommand = defineCommand({
58520
+ path: ["task", "policy", "set"],
58521
+ summary: "Require, or relax, the active-task rule for the project (owners and admins)",
58522
+ description: "Sets the project's task requirement. Relaxing needs --reason and is recorded as a ledger event and shown in the context packet; it is never silent. Agent tokens cannot change it.",
58523
+ args: [{ name: "enforcement", required: true, description: "required or relaxed" }],
58524
+ flags: [{ name: "reason", type: "string", value: "TEXT", description: "Why the rule is relaxed (required for relaxed)" }],
58525
+ examples: ["overlane task policy set required", 'overlane task policy set relaxed --reason "docs-only repository"'],
58526
+ effect: "write",
58527
+ ...common3,
58528
+ keywords: ["relax", "turn off task requirement", "require tasks", "allow edits without task", "enforcement"],
58529
+ result: TaskPolicySetResult,
58530
+ handler: async (inv) => setPolicy(inv.deps, { enforcement: inv.positionals[0], reason: textFlag(inv, "reason"), dryRun: inv.dryRun })
58531
+ });
58532
+ var queueCommands = [taskNewCommand, taskNextCommand, taskQueueCommand, taskPrioritiseCommand, taskPolicyCommand, taskPolicySetCommand];
58533
+
58232
58534
  // ../cli/src/task/results.ts
58233
58535
  init_zod();
58234
58536
  var TaskListResult = external_exports.object({ tasks: external_exports.array(TaskSummary) });
@@ -58267,34 +58569,35 @@ var TaskHandoffResult = withDryRun(
58267
58569
  );
58268
58570
 
58269
58571
  // ../cli/src/commands/task.ts
58270
- var common3 = { needsAuth: true, needsNetwork: true };
58572
+ var common4 = { needsAuth: true, needsNetwork: true };
58271
58573
  var taskListCommand = defineCommand({
58272
58574
  path: ["task", "list"],
58273
58575
  summary: "List the project's tasks and their states",
58274
58576
  description: "Lists every task of the connected project with its state, pause reason, version, lease holder, checks and latest checkpoint.",
58275
58577
  examples: ["overlane task list"],
58276
58578
  effect: "read",
58277
- ...common3,
58579
+ ...common4,
58278
58580
  keywords: ["tasks", "show all tasks", "see tasks", "backlog", "what tasks exist", "work items"],
58279
58581
  result: TaskListResult,
58280
58582
  handler: async (inv) => listTasks(inv.deps)
58281
58583
  });
58282
58584
  var taskStartCommand = defineCommand({
58283
58585
  path: ["task", "start"],
58284
- summary: "Create a task with a contract and claim it for this working copy",
58285
- description: "Creates a task (outcome, acceptance criteria, required checks, allowed paths) at the current commit and claims it, writing the lease to .harness/task.json. Fails with exit 5 if this working copy already holds a task.",
58586
+ summary: "Claim an existing task, or create one with a contract and claim it",
58587
+ description: "With a TASK_ID, claims that ready or paused task for this working copy (same checks as `task resume`). Without one, creates a task (outcome, acceptance criteria, required checks, allowed paths) at the current commit and claims it, writing the lease to .harness/task.json. Fails with exit 5 if this working copy already holds a task.",
58588
+ args: [{ name: "task-id", required: false, description: "An existing task to claim; omit to create one from the flags" }],
58286
58589
  flags: [
58287
- { name: "outcome", type: "string", required: true, value: "TEXT", description: "What the task must achieve (up to 500 characters)" },
58288
- { name: "criterion", type: "string", multiple: true, required: true, value: "TEXT", description: "An acceptance criterion; repeat for more" },
58590
+ { name: "outcome", type: "string", value: "TEXT", description: "What the task must achieve (up to 500 characters)" },
58591
+ { name: "criterion", type: "string", multiple: true, value: "TEXT", description: "An acceptance criterion; repeat for more" },
58289
58592
  { name: "check", type: "string", multiple: true, value: "ID:LEVEL", description: "A required check and its minimum evidence level, for example unit_tests:L2; repeat for more" },
58290
- { name: "path", type: "string", multiple: true, required: true, value: "GLOB", description: "A file pattern the task may change; repeat for more" }
58593
+ { name: "path", type: "string", multiple: true, value: "GLOB", description: "A file pattern the task may change; repeat for more" }
58291
58594
  ],
58292
- examples: ['overlane task start --outcome "Add CSV export" --criterion "export works" --check unit_tests:L2 --path "src/**"', 'overlane task start --outcome "Fix login" --criterion "login passes" --path "src/auth/**" --dry-run'],
58595
+ examples: ["overlane task start task-7", 'overlane task start --outcome "Add CSV export" --criterion "export works" --check unit_tests:L2 --path "src/**"', 'overlane task start --outcome "Fix login" --criterion "login passes" --path "src/auth/**" --dry-run'],
58293
58596
  effect: "write",
58294
- ...common3,
58597
+ ...common4,
58295
58598
  keywords: ["begin", "create task", "new task", "open", "claim new", "work item", "contract", "acceptance criteria", "start working"],
58296
58599
  result: TaskStartResult,
58297
- handler: async (inv) => startTask(inv.deps, { outcome: textFlag(inv, "outcome"), criteria: listFlag(inv, "criterion"), paths: listFlag(inv, "path"), checks: listFlag(inv, "check"), dryRun: inv.dryRun })
58600
+ handler: async (inv) => inv.positionals[0] !== void 0 ? startExisting(inv.deps, inv.positionals[0], inv.dryRun) : startTask(inv.deps, { outcome: textFlag(inv, "outcome"), criteria: listFlag(inv, "criterion"), paths: listFlag(inv, "path"), checks: listFlag(inv, "check"), dryRun: inv.dryRun })
58298
58601
  });
58299
58602
  var taskStatusCommand = defineCommand({
58300
58603
  path: ["task", "status"],
@@ -58302,7 +58605,7 @@ var taskStatusCommand = defineCommand({
58302
58605
  description: "Shows the held task from the service: state, lease, acceptance criteria, checks, evidence count and the latest checkpoint. Says so when nothing is held or the lease was lost.",
58303
58606
  examples: ["overlane task status"],
58304
58607
  effect: "read",
58305
- ...common3,
58608
+ ...common4,
58306
58609
  keywords: ["current task", "what am i working on", "lease", "active task", "progress", "held task"],
58307
58610
  result: TaskStatusResult,
58308
58611
  handler: async (inv) => taskStatus(inv.deps)
@@ -58318,7 +58621,7 @@ var taskCheckpointCommand = defineCommand({
58318
58621
  ],
58319
58622
  examples: ['overlane task checkpoint --summary "Parser done" --next "Write the tests"', 'overlane task checkpoint --summary "Out of budget" --next "Resume" --pause quota'],
58320
58623
  effect: "write",
58321
- ...common3,
58624
+ ...common4,
58322
58625
  keywords: ["save", "progress", "pause", "stop work", "park", "quota", "limit reached", "remember place", "snapshot", "save state", "out of budget"],
58323
58626
  result: TaskCheckpointResult,
58324
58627
  handler: async (inv) => checkpointTask(inv.deps, { summary: textFlag(inv, "summary"), next: textFlag(inv, "next"), pause: textFlag(inv, "pause"), dryRun: inv.dryRun })
@@ -58330,7 +58633,7 @@ var taskResumeCommand = defineCommand({
58330
58633
  args: [{ name: "task-id", required: true, description: "The task to resume" }],
58331
58634
  examples: ["overlane task resume task-1"],
58332
58635
  effect: "write",
58333
- ...common3,
58636
+ ...common4,
58334
58637
  keywords: ["continue", "pick up", "restart", "reclaim", "after pause", "take over", "carry on"],
58335
58638
  result: TaskResumeResult,
58336
58639
  handler: async (inv) => resumeTask(inv.deps, { taskId: inv.positionals[0], dryRun: inv.dryRun })
@@ -58341,7 +58644,7 @@ var taskSubmitCommand = defineCommand({
58341
58644
  description: "Asks for verification at HEAD. The task is verified only when evidence at or above each required check's level exists for that commit: L2 comes from CI on the pushed commit, L1 from `overlane task evidence`.",
58342
58645
  examples: ["overlane task submit", "overlane task submit --dry-run"],
58343
58646
  effect: "write",
58344
- ...common3,
58647
+ ...common4,
58345
58648
  keywords: ["finish", "done", "complete", "verify", "ready for review", "request verification", "hand in", "turn in"],
58346
58649
  result: TaskSubmitResult,
58347
58650
  handler: async (inv) => submitTask(inv.deps, { dryRun: inv.dryRun })
@@ -58357,7 +58660,7 @@ var taskEvidenceCommand = defineCommand({
58357
58660
  ],
58358
58661
  examples: ["overlane task evidence --level L1 -- pnpm test"],
58359
58662
  effect: "write",
58360
- ...common3,
58663
+ ...common4,
58361
58664
  keywords: ["tests", "prove", "record test result", "verification", "run checks", "L1", "attest", "run the tests and record"],
58362
58665
  result: TaskEvidenceResult,
58363
58666
  handler: async (inv) => recordEvidence(inv.deps, { level: textFlag(inv, "level"), task: textFlag(inv, "task"), words: inv.positionals, dryRun: inv.dryRun })
@@ -58373,7 +58676,7 @@ var taskHandoffCommand = defineCommand({
58373
58676
  ],
58374
58677
  examples: ["overlane task handoff --to codex", 'overlane task handoff --to claude --summary "API done" --next "Add tests"'],
58375
58678
  effect: "write",
58376
- ...common3,
58679
+ ...common4,
58377
58680
  keywords: ["hand off", "transfer", "give to", "switch agent", "other agent", "codex", "claude", "pass the task", "delegate", "move work", "swap agents"],
58378
58681
  result: TaskHandoffResult,
58379
58682
  handler: async (inv) => handoffTask(inv.deps, { summary: textFlag(inv, "summary"), next: textFlag(inv, "next"), to: textFlag(inv, "to"), dryRun: inv.dryRun })
@@ -58393,6 +58696,7 @@ function coreCommands() {
58393
58696
  doctorCommand,
58394
58697
  disconnectCommand,
58395
58698
  ...taskCommands,
58699
+ ...queueCommands,
58396
58700
  ...runCommands,
58397
58701
  ...releaseCommands,
58398
58702
  ...identityCommands
@@ -58614,35 +58918,35 @@ init_src2();
58614
58918
 
58615
58919
  // src/data-dir.ts
58616
58920
  import { homedir } from "node:os";
58617
- import { join as join24 } from "node:path";
58921
+ import { join as join25 } from "node:path";
58618
58922
  function dataDir(env = process.env, home = homedir()) {
58619
58923
  const override = env["MVRX_DATA_DIR"];
58620
58924
  if (override !== void 0 && override !== "") return override;
58621
- const base2 = env["XDG_DATA_HOME"] ?? (process.platform === "win32" ? env["LOCALAPPDATA"] : void 0) ?? (process.platform === "darwin" ? join24(home, "Library", "Application Support") : join24(home, ".local", "share"));
58622
- return join24(base2, "mvrx-harness");
58925
+ const base2 = env["XDG_DATA_HOME"] ?? (process.platform === "win32" ? env["LOCALAPPDATA"] : void 0) ?? (process.platform === "darwin" ? join25(home, "Library", "Application Support") : join25(home, ".local", "share"));
58926
+ return join25(base2, "mvrx-harness");
58623
58927
  }
58624
58928
  function marketplaceRoot(env = process.env, home = homedir()) {
58625
- return join24(dataDir(env, home), "marketplace");
58929
+ return join25(dataDir(env, home), "marketplace");
58626
58930
  }
58627
58931
 
58628
58932
  // src/plugin.ts
58629
58933
  import { readFileSync as readFileSync6 } from "node:fs";
58630
- import { join as join26 } from "node:path";
58934
+ import { join as join27 } from "node:path";
58631
58935
  import { parseArgs as parseArgs3 } from "node:util";
58632
58936
 
58633
58937
  // src/marketplace.ts
58634
58938
  init_src();
58635
58939
  import { createHash as createHash7 } from "node:crypto";
58636
- import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync7, readdirSync as readdirSync3, readFileSync as readFileSync5, renameSync as renameSync5, rmSync as rmSync4, statSync, writeFileSync as writeFileSync6 } from "node:fs";
58637
- import { dirname as dirname7, join as join25, relative, sep } from "node:path";
58940
+ import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync8, readdirSync as readdirSync3, readFileSync as readFileSync5, renameSync as renameSync6, rmSync as rmSync4, statSync, writeFileSync as writeFileSync7 } from "node:fs";
58941
+ import { dirname as dirname8, join as join26, relative, sep } from "node:path";
58638
58942
  var CLIENT_DIRS = ["claude", "codex"];
58639
58943
  var EMBEDDED_MANIFEST = "release-manifest.json";
58640
- var INSTALLED_MANIFEST = join25(".release", "manifest.json");
58944
+ var INSTALLED_MANIFEST = join26(".release", "manifest.json");
58641
58945
  var MarketplaceError = class extends Error {
58642
58946
  };
58643
58947
  function loadEmbedded(packageRoot2) {
58644
- const dir = join25(packageRoot2, "plugins");
58645
- const path = join25(dir, EMBEDDED_MANIFEST);
58948
+ const dir = join26(packageRoot2, "plugins");
58949
+ const path = join26(dir, EMBEDDED_MANIFEST);
58646
58950
  if (!existsSync5(path)) throw new MarketplaceError(`this package has no embedded plugin release (${path} is missing)`);
58647
58951
  const parsed = ReleaseManifest.safeParse(JSON.parse(readFileSync5(path, "utf8")));
58648
58952
  if (!parsed.success) throw new MarketplaceError(`the embedded release manifest is invalid: ${parsed.error.message}`);
@@ -58655,7 +58959,7 @@ function listFiles(root, dir = root) {
58655
58959
  if (!existsSync5(dir)) return [];
58656
58960
  const out2 = [];
58657
58961
  for (const entry of readdirSync3(dir, { withFileTypes: true })) {
58658
- const full = join25(dir, entry.name);
58962
+ const full = join26(dir, entry.name);
58659
58963
  if (entry.isDirectory()) out2.push(...listFiles(root, full));
58660
58964
  else out2.push(relative(root, full).split(sep).join("/"));
58661
58965
  }
@@ -58667,7 +58971,7 @@ async function verifyTree(treeRoot, manifest) {
58667
58971
  if (recomputed !== manifest.digest) problems.push(`manifest digest ${manifest.digest} does not match its file list (${recomputed})`);
58668
58972
  const listed = new Set(manifest.files.map((file2) => file2.path));
58669
58973
  for (const file2 of manifest.files) {
58670
- const path = join25(treeRoot, file2.path);
58974
+ const path = join26(treeRoot, file2.path);
58671
58975
  if (!existsSync5(path)) {
58672
58976
  problems.push(`missing: ${file2.path}`);
58673
58977
  continue;
@@ -58675,7 +58979,7 @@ async function verifyTree(treeRoot, manifest) {
58675
58979
  if (sha2562(readFileSync5(path)) !== file2.digest) problems.push(`modified: ${file2.path}`);
58676
58980
  }
58677
58981
  for (const client of CLIENT_DIRS) {
58678
- for (const found of listFiles(join25(treeRoot, client))) {
58982
+ for (const found of listFiles(join26(treeRoot, client))) {
58679
58983
  if (!listed.has(`${client}/${found}`)) problems.push(`unlisted: ${client}/${found}`);
58680
58984
  }
58681
58985
  }
@@ -58683,7 +58987,7 @@ async function verifyTree(treeRoot, manifest) {
58683
58987
  }
58684
58988
  function readInstalledManifest(target) {
58685
58989
  try {
58686
- const parsed = ReleaseManifest.safeParse(JSON.parse(readFileSync5(join25(target, INSTALLED_MANIFEST), "utf8")));
58990
+ const parsed = ReleaseManifest.safeParse(JSON.parse(readFileSync5(join26(target, INSTALLED_MANIFEST), "utf8")));
58687
58991
  return parsed.success ? parsed.data : null;
58688
58992
  } catch {
58689
58993
  return null;
@@ -58708,23 +59012,23 @@ async function syncMarketplace(embedded, target) {
58708
59012
  const staging = `${target}.new-${process.pid}`;
58709
59013
  const previous = `${target}.old-${process.pid}`;
58710
59014
  rmSync4(staging, { recursive: true, force: true });
58711
- mkdirSync7(staging, { recursive: true });
59015
+ mkdirSync8(staging, { recursive: true });
58712
59016
  try {
58713
59017
  for (const client of CLIENT_DIRS) {
58714
- if (existsSync5(join25(embedded.dir, client))) cpSync(join25(embedded.dir, client), join25(staging, client), { recursive: true });
59018
+ if (existsSync5(join26(embedded.dir, client))) cpSync(join26(embedded.dir, client), join26(staging, client), { recursive: true });
58715
59019
  }
58716
- mkdirSync7(join25(staging, ".release"), { recursive: true });
58717
- writeFileSync6(join25(staging, INSTALLED_MANIFEST), `${JSON.stringify(embedded.manifest, null, 2)}
59020
+ mkdirSync8(join26(staging, ".release"), { recursive: true });
59021
+ writeFileSync7(join26(staging, INSTALLED_MANIFEST), `${JSON.stringify(embedded.manifest, null, 2)}
58718
59022
  `);
58719
59023
  const after = await verifyTree(staging, embedded.manifest);
58720
59024
  if (after.length > 0) throw new MarketplaceError(`the copied plugin files do not match the release manifest:
58721
59025
  ${after.join("\n ")}`);
58722
- mkdirSync7(dirname7(target), { recursive: true });
58723
- if (existsSync5(target)) renameSync5(target, previous);
59026
+ mkdirSync8(dirname8(target), { recursive: true });
59027
+ if (existsSync5(target)) renameSync6(target, previous);
58724
59028
  try {
58725
- renameSync5(staging, target);
59029
+ renameSync6(staging, target);
58726
59030
  } catch (error62) {
58727
- if (existsSync5(previous)) renameSync5(previous, target);
59031
+ if (existsSync5(previous)) renameSync6(previous, target);
58728
59032
  throw error62;
58729
59033
  }
58730
59034
  rmSync4(previous, { recursive: true, force: true });
@@ -58746,7 +59050,7 @@ var PLUGIN_USAGE = ` overlane plugin install [--scope project|user] [--client c
58746
59050
  var PluginUsageError = class extends Error {
58747
59051
  };
58748
59052
  function readNames(treeRoot, client) {
58749
- const file2 = client === "claude" ? join26(treeRoot, "claude", ".claude-plugin", "marketplace.json") : join26(treeRoot, "codex", ".agents", "plugins", "marketplace.json");
59053
+ const file2 = client === "claude" ? join27(treeRoot, "claude", ".claude-plugin", "marketplace.json") : join27(treeRoot, "codex", ".agents", "plugins", "marketplace.json");
58750
59054
  const parsed = JSON.parse(readFileSync6(file2, "utf8"));
58751
59055
  const record2 = parsed;
58752
59056
  const plugin = record2.plugins?.[0]?.name;
@@ -58793,7 +59097,7 @@ ${PLUGIN_USAGE}`);
58793
59097
  const key = `${names.plugin}@${names.marketplace}`;
58794
59098
  if (!await available(deps, client)) {
58795
59099
  if (explicit !== void 0) {
58796
- deps.stderr(`overlane: \`${client}\` was not found on PATH; the marketplace is at ${join26(root, client)}
59100
+ deps.stderr(`overlane: \`${client}\` was not found on PATH; the marketplace is at ${join27(root, client)}
58797
59101
  `);
58798
59102
  failed = true;
58799
59103
  } else {
@@ -58805,7 +59109,7 @@ ${PLUGIN_USAGE}`);
58805
59109
  ranAny = true;
58806
59110
  deps.stdout(`${client}:
58807
59111
  `);
58808
- const dir = join26(root, client);
59112
+ const dir = join27(root, client);
58809
59113
  const steps = client === "claude" ? [
58810
59114
  ["claude", ["plugin", "marketplace", "add", dir, "--scope", scope]],
58811
59115
  ["claude", ["plugin", "marketplace", "update", names.marketplace]],
@@ -58973,7 +59277,7 @@ var packageCommands = [indexBuildCommand, indexUploadCommand, shimCommand, plugi
58973
59277
  // src/deps.ts
58974
59278
  import { execFile as execFile3, spawn } from "node:child_process";
58975
59279
  import { homedir as homedir3 } from "node:os";
58976
- import { join as join29 } from "node:path";
59280
+ import { join as join30 } from "node:path";
58977
59281
  import { createInterface } from "node:readline/promises";
58978
59282
  function exec(command, args2, options) {
58979
59283
  return new Promise((resolveResult) => {
@@ -59019,8 +59323,8 @@ async function confirm(question) {
59019
59323
  }
59020
59324
  }
59021
59325
  function configDir2(env) {
59022
- const base2 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join29(homedir3(), ".config");
59023
- return join29(base2, "mvrx-harness");
59326
+ const base2 = env["XDG_CONFIG_HOME"] ?? (process.platform === "win32" ? env["APPDATA"] : void 0) ?? join30(homedir3(), ".config");
59327
+ return join30(base2, "mvrx-harness");
59024
59328
  }
59025
59329
  function createDeps2(env = process.env) {
59026
59330
  return {