overlord-cli 0.2607292110.0 → 0.2607301714.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12437,8 +12437,102 @@ var init_util2 = __esm({
12437
12437
  });
12438
12438
 
12439
12439
  // ../packages/core/dist/service/local-target/project-metadata.js
12440
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
12440
+ import { execFileSync } from "node:child_process";
12441
+ import { chmodSync as chmodSync3, existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
12441
12442
  import path11 from "node:path";
12443
+ function writeIfChanged(filePath, content) {
12444
+ if (!existsSync11(filePath) || readFileSync9(filePath, "utf8") !== content) {
12445
+ writeFileSync4(filePath, content);
12446
+ }
12447
+ }
12448
+ function replaceManagedBlock(content, block) {
12449
+ const blockPattern = new RegExp(`${INSTRUCTION_BLOCK_START}[\\s\\S]*?${INSTRUCTION_BLOCK_END}\\n?`, "g");
12450
+ const withoutExisting = content.replace(blockPattern, "").trimEnd();
12451
+ return `${withoutExisting}${withoutExisting ? "\n\n" : ""}${block}
12452
+ `;
12453
+ }
12454
+ function ensureAgentInstructions(checkoutPath) {
12455
+ for (const filename of ["AGENTS.md", "CLAUDE.md"]) {
12456
+ const instructionPath = path11.join(checkoutPath, filename);
12457
+ const existing = existsSync11(instructionPath) ? readFileSync9(instructionPath, "utf8") : "";
12458
+ writeIfChanged(instructionPath, replaceManagedBlock(existing, PROJECT_METADATA_INSTRUCTION));
12459
+ }
12460
+ }
12461
+ function ensureGitignore(checkoutPath) {
12462
+ const gitignorePath = path11.join(checkoutPath, ".gitignore");
12463
+ const existing = existsSync11(gitignorePath) ? readFileSync9(gitignorePath, "utf8") : "";
12464
+ const existingPatterns = new Set(existing.split(/\r?\n/).map((line) => line.trim().replace(/^\//, "")).filter(Boolean));
12465
+ const additions = [".overlord/tmp/", ".overlord/logs/"].filter((pattern) => !existingPatterns.has(pattern));
12466
+ if (additions.length === 0)
12467
+ return;
12468
+ const separator = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
12469
+ writeFileSync4(gitignorePath, `${existing}${separator}${additions.join("\n")}
12470
+ `);
12471
+ }
12472
+ function resolveGitRoot(directoryPath) {
12473
+ try {
12474
+ return execFileSync("git", ["-C", directoryPath, "rev-parse", "--show-toplevel"], {
12475
+ encoding: "utf8",
12476
+ stdio: ["ignore", "pipe", "ignore"]
12477
+ }).trim();
12478
+ } catch {
12479
+ return null;
12480
+ }
12481
+ }
12482
+ function resolveGitHooksDirectory(gitRoot) {
12483
+ try {
12484
+ const gitPath2 = execFileSync("git", ["-C", gitRoot, "rev-parse", "--git-path", "hooks"], {
12485
+ encoding: "utf8",
12486
+ stdio: ["ignore", "pipe", "ignore"]
12487
+ }).trim();
12488
+ return path11.isAbsolute(gitPath2) ? gitPath2 : path11.resolve(gitRoot, gitPath2);
12489
+ } catch {
12490
+ return null;
12491
+ }
12492
+ }
12493
+ function ensurePreCommitGuard(gitRoot) {
12494
+ const hooksDirectory = resolveGitHooksDirectory(gitRoot);
12495
+ if (!hooksDirectory)
12496
+ return;
12497
+ mkdirSync5(hooksDirectory, { recursive: true });
12498
+ const guardPath = path11.join(hooksDirectory, HOOK_GUARD_FILENAME);
12499
+ writeIfChanged(guardPath, `#!/bin/sh
12500
+ # Managed by Overlord: reject any staged project-link metadata change.
12501
+ if git diff --cached --quiet -- .overlord/project.json; then
12502
+ exit 0
12503
+ fi
12504
+ echo "Overlord blocked this commit: .overlord/project.json is managed metadata and must not be changed." >&2
12505
+ exit 1
12506
+ `);
12507
+ chmodSync3(guardPath, 493);
12508
+ const preCommitPath = path11.join(hooksDirectory, "pre-commit");
12509
+ const hookBlock = `${HOOK_BLOCK_START}
12510
+ "$(dirname "$0")/${HOOK_GUARD_FILENAME}" || exit $?
12511
+ ${HOOK_BLOCK_END}`;
12512
+ if (!existsSync11(preCommitPath)) {
12513
+ writeFileSync4(preCommitPath, `#!/bin/sh
12514
+ ${hookBlock}
12515
+ `);
12516
+ chmodSync3(preCommitPath, 493);
12517
+ return;
12518
+ }
12519
+ const existing = readFileSync9(preCommitPath, "utf8");
12520
+ const blockPattern = new RegExp(`${HOOK_BLOCK_START}[\\s\\S]*?${HOOK_BLOCK_END}\\n?`, "g");
12521
+ const updated = `${existing.replace(blockPattern, "").trimEnd()}
12522
+
12523
+ ${hookBlock}
12524
+ `;
12525
+ writeIfChanged(preCommitPath, updated);
12526
+ chmodSync3(preCommitPath, 493);
12527
+ }
12528
+ function protectProjectMetadata(directoryPath) {
12529
+ const gitRoot = resolveGitRoot(directoryPath);
12530
+ const checkoutPath = gitRoot ?? directoryPath;
12531
+ ensureAgentInstructions(checkoutPath);
12532
+ ensureGitignore(checkoutPath);
12533
+ if (gitRoot)
12534
+ ensurePreCommitGuard(gitRoot);
12535
+ }
12442
12536
  function parseProjectJson(projectJsonPath) {
12443
12537
  if (!existsSync11(projectJsonPath))
12444
12538
  return null;
@@ -12446,12 +12540,13 @@ function parseProjectJson(projectJsonPath) {
12446
12540
  if (typeof parsed.projectId !== "string" || typeof parsed.resourceId !== "string")
12447
12541
  return null;
12448
12542
  const resourceIdsByExecutionTarget = parsed.resourceIdsByExecutionTarget && typeof parsed.resourceIdsByExecutionTarget === "object" && !Array.isArray(parsed.resourceIdsByExecutionTarget) ? Object.fromEntries(Object.entries(parsed.resourceIdsByExecutionTarget).filter((entry) => typeof entry[0] === "string" && entry[0].trim().length > 0 && typeof entry[1] === "string" && entry[1].trim().length > 0)) : {};
12543
+ const resourceKey = typeof parsed.resourceKey === "string" && parsed.resourceKey.trim().length > 0 ? parsed.resourceKey.trim() : void 0;
12449
12544
  return {
12450
- _warning: typeof parsed._warning === "string" ? parsed._warning : "This file is managed by Overlord and is regenerated automatically when this folder is linked as a project resource. Do not edit it manually \u2014 manual changes will be overwritten.",
12545
+ _warning: typeof parsed._warning === "string" ? parsed._warning : PROJECT_JSON_WARNING,
12451
12546
  version: typeof parsed.version === "number" ? parsed.version : 1,
12452
12547
  projectId: parsed.projectId,
12453
12548
  resourceId: parsed.resourceId,
12454
- resourceKey: typeof parsed.resourceKey === "string" && parsed.resourceKey.trim().length > 0 ? parsed.resourceKey.trim() : void 0,
12549
+ ...resourceKey ? { resourceKey } : {},
12455
12550
  resourceIdsByExecutionTarget,
12456
12551
  isPrimary: parsed.isPrimary === true,
12457
12552
  linkedAt: typeof parsed.linkedAt === "string" ? parsed.linkedAt : nowIso()
@@ -12476,6 +12571,7 @@ function writeProjectJson({ directoryPath, projectId, resourceId, resourceKey, e
12476
12571
  mkdirSync5(overlordDir, { recursive: true });
12477
12572
  mkdirSync5(path11.join(overlordDir, "tmp"), { recursive: true });
12478
12573
  mkdirSync5(path11.join(overlordDir, "logs"), { recursive: true });
12574
+ protectProjectMetadata(directoryPath);
12479
12575
  const projectJsonPath = path11.join(overlordDir, "project.json");
12480
12576
  const existing = readProjectJsonLink(projectJsonPath);
12481
12577
  const resourceIdsByExecutionTarget = {
@@ -12485,7 +12581,7 @@ function writeProjectJson({ directoryPath, projectId, resourceId, resourceKey, e
12485
12581
  resourceIdsByExecutionTarget[executionTargetId.trim()] = resourceId;
12486
12582
  }
12487
12583
  writeFileSync4(projectJsonPath, `${JSON.stringify({
12488
- _warning: "This file is managed by Overlord and is regenerated automatically when this folder is linked as a project resource. Do not edit it manually \u2014 manual changes will be overwritten.",
12584
+ _warning: PROJECT_JSON_WARNING,
12489
12585
  version: PROJECT_JSON_VERSION,
12490
12586
  projectId,
12491
12587
  resourceId,
@@ -12497,21 +12593,34 @@ function writeProjectJson({ directoryPath, projectId, resourceId, resourceKey, e
12497
12593
  `);
12498
12594
  return projectJsonPath;
12499
12595
  }
12500
- var PROJECT_JSON_VERSION;
12596
+ var PROJECT_JSON_VERSION, PROJECT_JSON_WARNING, INSTRUCTION_BLOCK_START, INSTRUCTION_BLOCK_END, PROJECT_METADATA_INSTRUCTION, HOOK_GUARD_FILENAME, HOOK_BLOCK_START, HOOK_BLOCK_END;
12501
12597
  var init_project_metadata = __esm({
12502
12598
  "../packages/core/dist/service/local-target/project-metadata.js"() {
12503
12599
  "use strict";
12504
12600
  init_util2();
12505
12601
  PROJECT_JSON_VERSION = 2;
12602
+ PROJECT_JSON_WARNING = "STRICTLY PROTECTED: This file is managed exclusively by Overlord. Agents and users must not edit, replace, stage, commit, or delete it. Re-link the resource with Overlord to change it.";
12603
+ INSTRUCTION_BLOCK_START = "<!-- OVERLORD PROJECT METADATA PROTECTION: START -->";
12604
+ INSTRUCTION_BLOCK_END = "<!-- OVERLORD PROJECT METADATA PROTECTION: END -->";
12605
+ PROJECT_METADATA_INSTRUCTION = `${INSTRUCTION_BLOCK_START}
12606
+ ## Overlord project metadata \u2014 do not edit
12607
+
12608
+ \`.overlord/project.json\` is exclusively managed by Overlord. Do not edit,
12609
+ replace, stage, commit, delete, or revert it. If its link metadata needs to
12610
+ change, use Overlord's resource-linking command instead.
12611
+ ${INSTRUCTION_BLOCK_END}`;
12612
+ HOOK_GUARD_FILENAME = "overlord-project-json-guard";
12613
+ HOOK_BLOCK_START = "# >>> Overlord project metadata guard >>>";
12614
+ HOOK_BLOCK_END = "# <<< Overlord project metadata guard <<<";
12506
12615
  }
12507
12616
  });
12508
12617
 
12509
12618
  // ../packages/core/dist/repository/git-tree.js
12510
- import { execFileSync } from "node:child_process";
12619
+ import { execFileSync as execFileSync2 } from "node:child_process";
12511
12620
  import path12 from "node:path";
12512
12621
  function runGit(cwd, args) {
12513
12622
  try {
12514
- return execFileSync("git", args, {
12623
+ return execFileSync2("git", args, {
12515
12624
  cwd,
12516
12625
  encoding: "utf8",
12517
12626
  maxBuffer: 10 * 1024 * 1024,
@@ -12599,10 +12708,10 @@ var init_git_tree = __esm({
12599
12708
  });
12600
12709
 
12601
12710
  // ../packages/core/dist/service/local-target/git-run.js
12602
- import { execFileSync as execFileSync2 } from "node:child_process";
12711
+ import { execFileSync as execFileSync3 } from "node:child_process";
12603
12712
  function runGit2(cwd, args) {
12604
12713
  try {
12605
- return execFileSync2("git", args, {
12714
+ return execFileSync3("git", args, {
12606
12715
  cwd,
12607
12716
  encoding: "utf8",
12608
12717
  stdio: ["ignore", "pipe", "ignore"],
@@ -12614,7 +12723,7 @@ function runGit2(cwd, args) {
12614
12723
  }
12615
12724
  function runGitResult(cwd, args) {
12616
12725
  try {
12617
- const stdout = execFileSync2("git", args, {
12726
+ const stdout = execFileSync3("git", args, {
12618
12727
  cwd,
12619
12728
  encoding: "utf8",
12620
12729
  stdio: ["ignore", "pipe", "pipe"],
@@ -13001,10 +13110,10 @@ var init_commit_message_diff_git = __esm({
13001
13110
  });
13002
13111
 
13003
13112
  // ../packages/core/dist/service/local-target/doctor-checks.js
13004
- import { execFileSync as execFileSync3 } from "node:child_process";
13113
+ import { execFileSync as execFileSync4 } from "node:child_process";
13005
13114
  function commandOnPath(command, args) {
13006
13115
  try {
13007
- const detail = execFileSync3(command, args, {
13116
+ const detail = execFileSync4(command, args, {
13008
13117
  encoding: "utf8",
13009
13118
  stdio: ["ignore", "pipe", "ignore"]
13010
13119
  }).trim();
@@ -13498,13 +13607,13 @@ var init_branch_planning = __esm({
13498
13607
  });
13499
13608
 
13500
13609
  // src/branch-preparation.ts
13501
- import { execFileSync as execFileSync4 } from "node:child_process";
13610
+ import { execFileSync as execFileSync5 } from "node:child_process";
13502
13611
  import { existsSync as existsSync17, mkdirSync as mkdirSync7, statSync as statSync3 } from "node:fs";
13503
13612
  import os3 from "node:os";
13504
13613
  import path17 from "node:path";
13505
13614
  function runGit3(cwd, args, options = {}) {
13506
13615
  try {
13507
- return execFileSync4("git", args, {
13616
+ return execFileSync5("git", args, {
13508
13617
  cwd,
13509
13618
  encoding: "utf8",
13510
13619
  stdio: ["ignore", "pipe", "pipe"],
@@ -13519,7 +13628,7 @@ function runGit3(cwd, args, options = {}) {
13519
13628
  function lines(value) {
13520
13629
  return value.split("\n").map((line) => line.trim()).filter(Boolean);
13521
13630
  }
13522
- function resolveGitRoot(workingDirectory) {
13631
+ function resolveGitRoot2(workingDirectory) {
13523
13632
  const root = runGit3(workingDirectory, ["rev-parse", "--show-toplevel"]);
13524
13633
  if (!root) throw new Error(`${workingDirectory} is not inside a git repository.`);
13525
13634
  return path17.resolve(root);
@@ -13744,7 +13853,7 @@ async function prepareMissionBranch({
13744
13853
  if (options.dryRun) {
13745
13854
  return { workingDirectory: options.workingDirectory, branchAutomation: null };
13746
13855
  }
13747
- const gitRoot = resolveGitRoot(options.workingDirectory);
13856
+ const gitRoot = resolveGitRoot2(options.workingDirectory);
13748
13857
  const mission = await runtime.backend.get(
13749
13858
  `/api/missions/${encodeURIComponent(options.missionId)}`
13750
13859
  );
@@ -14373,7 +14482,7 @@ var init_terminal_launcher = __esm({
14373
14482
 
14374
14483
  // src/launch.ts
14375
14484
  import { spawnSync as spawnSync2 } from "node:child_process";
14376
- import { chmodSync as chmodSync3, writeFileSync as writeFileSync6 } from "node:fs";
14485
+ import { chmodSync as chmodSync4, writeFileSync as writeFileSync6 } from "node:fs";
14377
14486
  import path19 from "node:path";
14378
14487
  function overlordLaunchEnv({
14379
14488
  backendUrl,
@@ -14581,7 +14690,7 @@ Execution request: ${options.executionRequestId}` : context.launchContext;
14581
14690
  missionLink: { displayId: context.displayId, title: context.title }
14582
14691
  })
14583
14692
  );
14584
- chmodSync3(terminalScriptPath, 448);
14693
+ chmodSync4(terminalScriptPath, 448);
14585
14694
  }
14586
14695
  const execution = resolveLaunchExecution({
14587
14696
  command: command.command,
@@ -15390,7 +15499,7 @@ var init_vcs_sessions = __esm({
15390
15499
  });
15391
15500
 
15392
15501
  // src/vcs.ts
15393
- import { execFileSync as execFileSync5 } from "node:child_process";
15502
+ import { execFileSync as execFileSync6 } from "node:child_process";
15394
15503
  import { createHash as createHash6 } from "node:crypto";
15395
15504
  import {
15396
15505
  existsSync as existsSync20,
@@ -15426,7 +15535,7 @@ function hashWorktreeFile({
15426
15535
  filePath
15427
15536
  }) {
15428
15537
  try {
15429
- return execFileSync5("git", ["hash-object", filePath], {
15538
+ return execFileSync6("git", ["hash-object", filePath], {
15430
15539
  cwd: workingDirectory,
15431
15540
  encoding: "utf8",
15432
15541
  stdio: ["ignore", "pipe", "ignore"]
@@ -15437,7 +15546,7 @@ function hashWorktreeFile({
15437
15546
  }
15438
15547
  function readChangedFiles(workingDirectory) {
15439
15548
  try {
15440
- const output = execFileSync5("git", ["status", "--porcelain"], {
15549
+ const output = execFileSync6("git", ["status", "--porcelain"], {
15441
15550
  cwd: workingDirectory,
15442
15551
  encoding: "utf8",
15443
15552
  stdio: ["ignore", "pipe", "ignore"],
@@ -15578,7 +15687,7 @@ function normalizeAbsolute(filePath) {
15578
15687
  }
15579
15688
  function gitRepoRoot(workingDirectory) {
15580
15689
  try {
15581
- const root = execFileSync5("git", ["rev-parse", "--show-toplevel"], {
15690
+ const root = execFileSync6("git", ["rev-parse", "--show-toplevel"], {
15582
15691
  cwd: workingDirectory,
15583
15692
  encoding: "utf8",
15584
15693
  stdio: ["ignore", "pipe", "ignore"]
@@ -16301,13 +16410,13 @@ var init_runner_identity = __esm({
16301
16410
 
16302
16411
  // src/runner-service.ts
16303
16412
  import { execFile } from "node:child_process";
16304
- import { chmodSync as chmodSync4, existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync17, rmSync as rmSync5, writeFileSync as writeFileSync10 } from "node:fs";
16413
+ import { chmodSync as chmodSync5, existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync17, rmSync as rmSync5, writeFileSync as writeFileSync10 } from "node:fs";
16305
16414
  import os4 from "node:os";
16306
16415
  import path26 from "node:path";
16307
16416
  import { promisify } from "node:util";
16308
16417
  function writeServiceFile(filePath, contents) {
16309
16418
  writeFileSync10(filePath, contents, { mode: 384 });
16310
- chmodSync4(filePath, 384);
16419
+ chmodSync5(filePath, 384);
16311
16420
  }
16312
16421
  function emptyRunnerServiceState() {
16313
16422
  return {