@microsoft/agentrc 2.0.1-7 → 2.0.1-9

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
@@ -3052,7 +3052,7 @@ var require_main = __commonJS({
3052
3052
  exports.createMessageConnection = exports.createServerSocketTransport = exports.createClientSocketTransport = exports.createServerPipeTransport = exports.createClientPipeTransport = exports.generateRandomPipeName = exports.StreamMessageWriter = exports.StreamMessageReader = exports.SocketMessageWriter = exports.SocketMessageReader = exports.PortMessageWriter = exports.PortMessageReader = exports.IPCMessageWriter = exports.IPCMessageReader = void 0;
3053
3053
  var ril_1 = require_ril();
3054
3054
  ril_1.default.install();
3055
- var path21 = __require("path");
3055
+ var path23 = __require("path");
3056
3056
  var os2 = __require("os");
3057
3057
  var crypto_1 = __require("crypto");
3058
3058
  var net_1 = __require("net");
@@ -3188,9 +3188,9 @@ var require_main = __commonJS({
3188
3188
  }
3189
3189
  let result;
3190
3190
  if (XDG_RUNTIME_DIR) {
3191
- result = path21.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`);
3191
+ result = path23.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`);
3192
3192
  } else {
3193
- result = path21.join(os2.tmpdir(), `vscode-${randomSuffix}.sock`);
3193
+ result = path23.join(os2.tmpdir(), `vscode-${randomSuffix}.sock`);
3194
3194
  }
3195
3195
  const limit = safeIpcPathLengths.get(process.platform);
3196
3196
  if (limit !== void 0 && result.length > limit) {
@@ -6674,7 +6674,7 @@ async function checkReposForInstructions(token, repos, onProgress) {
6674
6674
  }
6675
6675
 
6676
6676
  // packages/core/src/services/batch.ts
6677
- import path9 from "path";
6677
+ import path10 from "path";
6678
6678
 
6679
6679
  // packages/core/src/utils/pr.ts
6680
6680
  function buildInstructionsPrBody() {
@@ -6958,7 +6958,7 @@ async function checkReposForInstructions2(token, repos, onProgress) {
6958
6958
 
6959
6959
  // packages/core/src/services/instructions.ts
6960
6960
  import fs5 from "fs/promises";
6961
- import path6 from "path";
6961
+ import path7 from "path";
6962
6962
 
6963
6963
  // packages/core/src/services/copilot.ts
6964
6964
  import fs4 from "fs/promises";
@@ -7378,6 +7378,25 @@ async function createCopilotClient(cliConfig) {
7378
7378
  }
7379
7379
  }
7380
7380
 
7381
+ // packages/core/src/services/skills.ts
7382
+ import path6 from "path";
7383
+ import { fileURLToPath as fileURLToPath2 } from "url";
7384
+ var overrideSkillsDir;
7385
+ function getBuiltinSkillsDir() {
7386
+ if (overrideSkillsDir) {
7387
+ return overrideSkillsDir;
7388
+ }
7389
+ const thisFile = fileURLToPath2(import.meta.url);
7390
+ const thisDir = path6.dirname(thisFile);
7391
+ if (thisDir.includes(path6.join("packages", "core", "src"))) {
7392
+ return path6.resolve(thisDir, "..", "..", "..", "..", "plugin", "skills");
7393
+ }
7394
+ return path6.resolve(thisDir, "skills");
7395
+ }
7396
+ function getSkillDirectory(_skillName) {
7397
+ return getBuiltinSkillsDir();
7398
+ }
7399
+
7381
7400
  // packages/core/src/services/instructions.ts
7382
7401
  async function detectExistingInstructions(repoPath, detailDirName = ".agents") {
7383
7402
  const { agentsMdFiles, claudeMdFiles } = await findInstructionMarkerFiles(repoPath);
@@ -7401,7 +7420,7 @@ async function findInstructionMarkerFiles(repoPath) {
7401
7420
  claudeMdFiles.push(relPath ? `${relPath}/${entry.name}` : entry.name);
7402
7421
  }
7403
7422
  } else if (entry.isDirectory()) {
7404
- await walk(path6.join(dir, entry.name), relPath ? `${relPath}/${entry.name}` : entry.name);
7423
+ await walk(path7.join(dir, entry.name), relPath ? `${relPath}/${entry.name}` : entry.name);
7405
7424
  }
7406
7425
  }
7407
7426
  }
@@ -7409,7 +7428,7 @@ async function findInstructionMarkerFiles(repoPath) {
7409
7428
  return { agentsMdFiles: agentsMdFiles.sort(), claudeMdFiles: claudeMdFiles.sort() };
7410
7429
  }
7411
7430
  async function findModularInstructionFiles(repoPath) {
7412
- const dir = path6.join(repoPath, ".github", "instructions");
7431
+ const dir = path7.join(repoPath, ".github", "instructions");
7413
7432
  const entries = await fs5.readdir(dir, { withFileTypes: true }).catch(() => []);
7414
7433
  return entries.filter((e) => !e.isSymbolicLink() && e.isFile() && e.name.endsWith(".instructions.md")).map((e) => `.github/instructions/${e.name}`).sort();
7415
7434
  }
@@ -7423,7 +7442,7 @@ async function findDetailFiles(repoPath, detailDirName) {
7423
7442
  if (entry.isSymbolicLink()) continue;
7424
7443
  if (entry.isDirectory()) {
7425
7444
  if (entry.name === detailDirName) {
7426
- const detailDir = path6.join(dir, entry.name);
7445
+ const detailDir = path7.join(dir, entry.name);
7427
7446
  const detailEntries = await fs5.readdir(detailDir, { withFileTypes: true }).catch(() => []);
7428
7447
  for (const de of detailEntries) {
7429
7448
  if (!de.isSymbolicLink() && de.isFile() && de.name.endsWith(".md")) {
@@ -7432,7 +7451,7 @@ async function findDetailFiles(repoPath, detailDirName) {
7432
7451
  }
7433
7452
  }
7434
7453
  } else {
7435
- await walk(path6.join(dir, entry.name), relPath ? `${relPath}/${entry.name}` : entry.name);
7454
+ await walk(path7.join(dir, entry.name), relPath ? `${relPath}/${entry.name}` : entry.name);
7436
7455
  }
7437
7456
  }
7438
7457
  }
@@ -7514,11 +7533,11 @@ function isCopilotAuthError(error) {
7514
7533
  return error instanceof Error && error.message.includes("Copilot CLI not logged in.");
7515
7534
  }
7516
7535
  function resolveAreaWorkingDirectory(repoPath, area) {
7517
- const repoRoot = path6.resolve(repoPath);
7536
+ const repoRoot = path7.resolve(repoPath);
7518
7537
  const rawWorkingDirectory = area?.workingDirectory ?? area?.path;
7519
7538
  if (!rawWorkingDirectory) return repoRoot;
7520
- const resolved = area?.workingDirectory ? path6.resolve(repoRoot, rawWorkingDirectory) : path6.isAbsolute(rawWorkingDirectory) ? path6.resolve(rawWorkingDirectory) : path6.resolve(repoRoot, rawWorkingDirectory);
7521
- if (resolved !== repoRoot && !resolved.startsWith(repoRoot + path6.sep)) {
7539
+ const resolved = area?.workingDirectory ? path7.resolve(repoRoot, rawWorkingDirectory) : path7.isAbsolute(rawWorkingDirectory) ? path7.resolve(rawWorkingDirectory) : path7.resolve(repoRoot, rawWorkingDirectory);
7540
+ if (resolved !== repoRoot && !resolved.startsWith(repoRoot + path7.sep)) {
7522
7541
  throw new Error(`Invalid workingDirectory "${rawWorkingDirectory}": escapes repo boundary`);
7523
7542
  }
7524
7543
  return resolved;
@@ -7550,6 +7569,7 @@ async function generateCopilotInstructions(options) {
7550
7569
  const preferredModel = options.model ?? DEFAULT_MODEL;
7551
7570
  const systemContent = hasExistingInstructions ? "You are an expert codebase analyst. Your task is to generate a concise .github/copilot-instructions.md that complements existing instruction files. Use the available tools (glob, view, grep) to explore the codebase. When done, call the emit_file_content tool with the final markdown." : "You are an expert codebase analyst. Your task is to generate a concise .github/copilot-instructions.md file. Use the available tools (glob, view, grep) to explore the codebase. When done, call the emit_file_content tool with the final markdown.";
7552
7571
  const { tool: emitTool, getContent } = await createEmitTool();
7572
+ const rootSkillDir = getSkillDirectory("root-instructions");
7553
7573
  const session = await client.createSession({
7554
7574
  model: preferredModel,
7555
7575
  streaming: true,
@@ -7560,7 +7580,8 @@ async function generateCopilotInstructions(options) {
7560
7580
  tools: [emitTool],
7561
7581
  excludedTools: INSTRUCTION_GENERATION_EXCLUDED_TOOLS,
7562
7582
  onPermissionRequest: READ_ONLY_PERMISSION_HANDLER,
7563
- infiniteSessions: { enabled: false }
7583
+ infiniteSessions: { enabled: false },
7584
+ skillDirectories: [rootSkillDir]
7564
7585
  });
7565
7586
  await trySetAutopilot(session);
7566
7587
  let content = "";
@@ -7581,22 +7602,8 @@ async function generateCopilotInstructions(options) {
7581
7602
  sessionError = getSessionError(errorMsg);
7582
7603
  }
7583
7604
  });
7584
- const prompt = `Analyze this codebase and generate a .github/copilot-instructions.md file.
7585
-
7586
- Fan out multiple Explore subagents to map out the codebase in parallel:
7587
- 1. Check for existing instruction files: glob for **/{.github/copilot-instructions.md,AGENT.md,CLAUDE.md,.cursorrules,README.md}
7588
- 2. Identify the tech stack: look at package.json, tsconfig.json, pyproject.toml, Cargo.toml, go.mod, *.csproj, *.fsproj, *.sln, global.json, build.gradle, pom.xml, etc.
7589
- 3. Understand the structure: list key directories
7590
- 4. Detect monorepo structures: check for workspace configs (npm/pnpm/yarn workspaces, Cargo.toml [workspace], go.work, .sln solution files, settings.gradle include directives, pom.xml modules)
7591
-
7592
- Generate concise instructions (~20-50 lines) covering:
7593
- - Tech stack and architecture
7594
- - Build/test commands
7595
- - Project-specific conventions
7596
- - Key files/directories
7597
- - Monorepo structure and per-app layout (if this is a monorepo, describe the workspace organization, how apps relate to each other, and any shared libraries)
7598
- ${existingSection}
7599
- When you have the complete markdown content, call the \`emit_file_content\` tool with it. Do NOT output the file content directly in chat.`;
7605
+ const prompt = `/root-instructions Analyze this codebase and generate a .github/copilot-instructions.md file.
7606
+ ${existingSection}`;
7600
7607
  progress("Analyzing codebase...");
7601
7608
  let sendError;
7602
7609
  try {
@@ -7633,6 +7640,7 @@ async function generateAreaInstructions(options) {
7633
7640
  const preferredModel = options.model ?? DEFAULT_MODEL;
7634
7641
  const areaSystemContent = hasExistingInstructions ? `You are an expert codebase analyst. Your task is to generate a concise .instructions.md file for a specific area of a codebase. This file will be used as an area instruction in VS Code, automatically applied when working on files matching certain patterns. This file should complement, not duplicate, existing instruction files. Use the Explore subagents and read-only tools to explore the codebase. When done, call the emit_file_content tool with the final markdown.` : `You are an expert codebase analyst. Your task is to generate a concise .instructions.md file for a specific area of a codebase. This file will be used as an area instruction in VS Code, automatically applied when working on files matching certain patterns. Use the Explore subagents and read-only tools to explore the codebase. When done, call the emit_file_content tool with the final markdown.`;
7635
7642
  const { tool: emitTool, getContent } = await createEmitTool();
7643
+ const areaSkillDir = getSkillDirectory("area-instructions");
7636
7644
  const session = await client.createSession({
7637
7645
  model: preferredModel,
7638
7646
  streaming: true,
@@ -7643,7 +7651,8 @@ async function generateAreaInstructions(options) {
7643
7651
  tools: [emitTool],
7644
7652
  excludedTools: INSTRUCTION_GENERATION_EXCLUDED_TOOLS,
7645
7653
  onPermissionRequest: READ_ONLY_PERMISSION_HANDLER,
7646
- infiniteSessions: { enabled: false }
7654
+ infiniteSessions: { enabled: false },
7655
+ skillDirectories: [areaSkillDir]
7647
7656
  });
7648
7657
  await trySetAutopilot(session);
7649
7658
  let content = "";
@@ -7664,30 +7673,13 @@ async function generateAreaInstructions(options) {
7664
7673
  sessionError = getSessionError(errorMsg);
7665
7674
  }
7666
7675
  });
7667
- const prompt = `Analyze the "${area.name}" area of this codebase and generate an area instruction file.
7676
+ const prompt = `/area-instructions Analyze the "${area.name}" area of this codebase and generate an area instruction file.
7668
7677
 
7669
7678
  This area covers files matching: ${applyToStr}
7670
7679
  ${area.description ? `Description: ${area.description}` : ""}
7671
-
7672
- Use tools to explore ONLY the files and directories within this area:
7673
- 1. List the key files: glob for ${applyToPatterns.map((p) => `"${p}"`).join(", ")}
7674
- 2. Identify the tech stack, dependencies, and frameworks used in this area
7675
- 3. Look at key source files to understand patterns and conventions specific to this area
7676
-
7677
- Generate concise instructions (~10-30 lines) covering:
7678
- - What this area does and its role in the overall project
7679
- - Area-specific tech stack, dependencies, and frameworks
7680
- - Coding conventions and patterns specific to this area
7681
- - Build/test commands relevant to this area (if different from root)
7682
- - Key files and directory structure within this area
7683
-
7684
- IMPORTANT:
7685
- - Focus ONLY on this specific area, not the whole repo
7686
- - Do NOT repeat repo-wide information (that goes in the root copilot-instructions.md)
7687
- - Keep it complementary to root instructions
7688
- ${existingSection ? `- Do NOT duplicate content already covered by existing instruction files
7689
- ${existingSection}` : ""}
7690
- - When you have the complete markdown content, call the \`emit_file_content\` tool with it. Do NOT output the file content directly in chat.`;
7680
+ ${existingSection ? `
7681
+ Do NOT duplicate content already covered by existing instruction files
7682
+ ${existingSection}` : ""}`;
7691
7683
  progress(`Analyzing area "${area.name}"...`);
7692
7684
  let sendError;
7693
7685
  try {
@@ -7724,7 +7716,7 @@ ${body}
7724
7716
  `;
7725
7717
  }
7726
7718
  function areaInstructionPath(repoPath, area) {
7727
- return path6.join(
7719
+ return path7.join(
7728
7720
  repoPath,
7729
7721
  ".github",
7730
7722
  "instructions",
@@ -7734,7 +7726,7 @@ function areaInstructionPath(repoPath, area) {
7734
7726
  async function writeAreaInstruction(repoPath, area, body, force) {
7735
7727
  const filePath = areaInstructionPath(repoPath, area);
7736
7728
  if (!body.trim()) return { status: "empty", filePath };
7737
- await ensureDir(path6.dirname(filePath));
7729
+ await ensureDir(path7.dirname(filePath));
7738
7730
  const { wrote, reason } = await safeWriteFile(
7739
7731
  filePath,
7740
7732
  buildAreaInstructionContent(area, body),
@@ -7746,13 +7738,13 @@ async function writeAreaInstruction(repoPath, area, body, force) {
7746
7738
  return { status: "written", filePath };
7747
7739
  }
7748
7740
  async function writeInstructionFile(repoPath, relativePath, content, force) {
7749
- const resolvedRoot = path6.resolve(repoPath);
7750
- const filePath = path6.resolve(repoPath, relativePath);
7751
- if (!filePath.startsWith(resolvedRoot + path6.sep) && filePath !== resolvedRoot) {
7741
+ const resolvedRoot = path7.resolve(repoPath);
7742
+ const filePath = path7.resolve(repoPath, relativePath);
7743
+ if (!filePath.startsWith(resolvedRoot + path7.sep) && filePath !== resolvedRoot) {
7752
7744
  throw new Error(`Invalid path: escapes repository root (${relativePath})`);
7753
7745
  }
7754
7746
  if (!content.trim()) return { status: "empty", filePath };
7755
- await ensureDir(path6.dirname(filePath));
7747
+ await ensureDir(path7.dirname(filePath));
7756
7748
  const { wrote, reason } = await safeWriteFile(filePath, content, Boolean(force));
7757
7749
  if (!wrote) {
7758
7750
  return { status: reason === "symlink" ? "symlink" : "skipped", filePath };
@@ -7836,6 +7828,7 @@ async function generateNestedHub(client, options) {
7836
7828
  const existingCtx = await detectExistingInstructions(options.repoPath, options.detailDir);
7837
7829
  const existingSection = buildExistingInstructionsSection(existingCtx);
7838
7830
  const { tool: emitTool, getContent } = await createEmitTool();
7831
+ const nestedSkillDir = getSkillDirectory("nested-hub");
7839
7832
  const session = await client.createSession({
7840
7833
  model,
7841
7834
  streaming: true,
@@ -7846,7 +7839,8 @@ async function generateNestedHub(client, options) {
7846
7839
  tools: [emitTool],
7847
7840
  excludedTools: INSTRUCTION_GENERATION_EXCLUDED_TOOLS,
7848
7841
  onPermissionRequest: READ_ONLY_PERMISSION_HANDLER,
7849
- infiniteSessions: { enabled: false }
7842
+ infiniteSessions: { enabled: false },
7843
+ skillDirectories: [nestedSkillDir]
7850
7844
  });
7851
7845
  await trySetAutopilot(session);
7852
7846
  let content = "";
@@ -7878,29 +7872,14 @@ ${options.childAreas.map((c) => `- ${c.name} (${c.path ?? "unknown path"})`).joi
7878
7872
  Include a "## Sub-Projects" section with links to each child's AGENTS.md.` : "";
7879
7873
  const parentContext = options.area?.parentArea ? `
7880
7874
  This is a sub-project of "${options.area.parentArea}". Include a note linking back to the parent area.` : "";
7881
- const prompt = `Analyze this codebase and generate a lean AGENTS.md hub file (~90-120 lines).${areaContext}${parentContext}
7882
-
7883
- Use tools to explore the codebase structure, tech stack, and conventions.
7875
+ const prompt = `/nested-hub Generate a lean AGENTS.md hub file (~90-120 lines).${areaContext}${parentContext}
7884
7876
 
7885
- The hub should contain:
7886
- - Project overview and purpose
7887
- - Key concepts and architecture
7888
- - Coding conventions and guardrails
7889
- - A "## Detailed Instructions" section listing links to detail files in \`${options.detailDir}/\`${childContext}
7877
+ Detail files go in \`${options.detailDir}/\`.${childContext}
7890
7878
 
7891
- At the END of your output, emit a fenced JSON block with recommended topics for detail files:
7892
- \`\`\`json
7893
- [{"slug":"testing","title":"Testing Guide","description":"How to write and run tests"},{"slug":"architecture","title":"Architecture","description":"Codebase structure and patterns"}]
7894
- \`\`\`
7895
-
7896
- Recommend 3-5 topics that would benefit from deep-dive detail files. Each slug becomes a filename: \`${options.detailDir}/{slug}.md\`.
7897
-
7898
- IMPORTANT:
7899
- - Keep the hub LEAN \u2014 overview and guardrails only, details go in separate files
7900
- - The JSON block will be parsed and removed from the final output
7901
- ${existingSection ? `- Do NOT duplicate content from existing instruction files
7902
- ${existingSection}` : ""}
7903
- - When you have the complete markdown content (including the trailing JSON topic block), call the \`emit_file_content\` tool with it. Do NOT output the content directly in chat.`;
7879
+ Recommend 3-5 topics for deep-dive detail files. Each slug becomes: \`${options.detailDir}/{slug}.md\`.
7880
+ ${existingSection ? `
7881
+ Do NOT duplicate content from existing instruction files
7882
+ ${existingSection}` : ""}`;
7904
7883
  let sendError;
7905
7884
  try {
7906
7885
  await session.sendAndWait({ prompt }, 18e4);
@@ -7924,6 +7903,7 @@ async function generateNestedDetail(client, options) {
7924
7903
  });
7925
7904
  const model = options.model ?? DEFAULT_MODEL;
7926
7905
  const { tool: emitTool, getContent } = await createEmitTool();
7906
+ const detailSkillDir = getSkillDirectory("nested-detail");
7927
7907
  const session = await client.createSession({
7928
7908
  model,
7929
7909
  streaming: true,
@@ -7934,7 +7914,8 @@ async function generateNestedDetail(client, options) {
7934
7914
  tools: [emitTool],
7935
7915
  excludedTools: INSTRUCTION_GENERATION_EXCLUDED_TOOLS,
7936
7916
  onPermissionRequest: READ_ONLY_PERMISSION_HANDLER,
7937
- infiniteSessions: { enabled: false }
7917
+ infiniteSessions: { enabled: false },
7918
+ skillDirectories: [detailSkillDir]
7938
7919
  });
7939
7920
  await trySetAutopilot(session);
7940
7921
  let content = "";
@@ -7956,22 +7937,11 @@ async function generateNestedDetail(client, options) {
7956
7937
  }
7957
7938
  });
7958
7939
  const areaContext = options.area ? `Focus on the "${options.area.name}" area (files matching: ${Array.isArray(options.area.applyTo) ? options.area.applyTo.join(", ") : options.area.applyTo}).` : "Focus on the entire repository.";
7959
- const prompt = `Generate a deep-dive instruction file about "${options.topic.title}" for this codebase.
7940
+ const prompt = `/nested-detail Generate a deep-dive instruction file about "${options.topic.title}" for this codebase.
7960
7941
  ${areaContext}
7961
7942
 
7962
7943
  Topic: ${options.topic.title}
7963
- Description: ${options.topic.description}
7964
-
7965
- Use tools to explore the codebase and understand the specific patterns, APIs, and conventions related to this topic.
7966
-
7967
- The file should:
7968
- - Start with \`# ${options.topic.title}\`
7969
- - Include \`**When to read:** {one-line trigger condition}\` right after the heading
7970
- - Cover ~50-100 lines of practical, actionable guidance
7971
- - Include code patterns and examples found in the actual codebase
7972
- - Be specific to this codebase, not generic advice
7973
-
7974
- When you have the complete markdown content, call the \`emit_file_content\` tool with it. Do NOT output the content directly in chat.`;
7944
+ Description: ${options.topic.description}`;
7975
7945
  let sendError;
7976
7946
  try {
7977
7947
  await session.sendAndWait({ prompt }, 18e4);
@@ -8006,7 +7976,7 @@ async function generateNestedInstructions(options) {
8006
7976
  onProgress: options.onProgress
8007
7977
  });
8008
7978
  const basePath = options.area?.path ?? ".";
8009
- const hubRelativePath = path6.join(basePath, "AGENTS.md");
7979
+ const hubRelativePath = path7.join(basePath, "AGENTS.md");
8010
7980
  let finalHubContent = hubContent;
8011
7981
  if (options.area) {
8012
7982
  finalHubContent = `${buildAreaFrontmatter(options.area)}
@@ -8030,7 +8000,7 @@ ${hubContent}`;
8030
8000
  });
8031
8001
  if (detailContent) {
8032
8002
  result.details.push({
8033
- relativePath: path6.join(basePath, options.detailDir, `${topic.slug}.md`),
8003
+ relativePath: path7.join(basePath, options.detailDir, `${topic.slug}.md`),
8034
8004
  content: detailContent,
8035
8005
  topic: topic.title
8036
8006
  });
@@ -8045,7 +8015,7 @@ ${hubContent}`;
8045
8015
  }
8046
8016
  if (options.claudeMd) {
8047
8017
  result.claudeMd = {
8048
- relativePath: path6.join(basePath, "CLAUDE.md"),
8018
+ relativePath: path7.join(basePath, "CLAUDE.md"),
8049
8019
  content: "@AGENTS.md\n"
8050
8020
  };
8051
8021
  }
@@ -8068,11 +8038,11 @@ async function generateNestedAreaInstructions(options) {
8068
8038
 
8069
8039
  // packages/core/src/services/readiness.ts
8070
8040
  import fs7 from "fs/promises";
8071
- import path8 from "path";
8041
+ import path9 from "path";
8072
8042
 
8073
8043
  // packages/core/src/services/policy.ts
8074
8044
  import fs6 from "fs/promises";
8075
- import path7 from "path";
8045
+ import path8 from "path";
8076
8046
  var DEFAULT_PASS_RATE = 0.8;
8077
8047
  function validatePolicyConfig(obj, source, format = "module") {
8078
8048
  if (typeof obj !== "object" || obj === null) {
@@ -8165,8 +8135,8 @@ function parsePolicySources(raw) {
8165
8135
  }
8166
8136
  async function loadPolicy(source, options) {
8167
8137
  const jsonOnly = options?.jsonOnly ?? false;
8168
- if (source.startsWith(".") || path7.isAbsolute(source)) {
8169
- const resolved = path7.resolve(source);
8138
+ if (source.startsWith(".") || path8.isAbsolute(source)) {
8139
+ const resolved = path8.resolve(source);
8170
8140
  if (resolved.endsWith(".json")) {
8171
8141
  const data = await readJson(resolved);
8172
8142
  if (!data) {
@@ -8797,7 +8767,7 @@ async function runReadinessReport(options) {
8797
8767
  const repoPath = options.repoPath;
8798
8768
  const analysis = await analyzeRepo(repoPath);
8799
8769
  const rootFiles = await safeReadDir(repoPath);
8800
- const rootPackageJson = await readJson(path8.join(repoPath, "package.json"));
8770
+ const rootPackageJson = await readJson(path9.join(repoPath, "package.json"));
8801
8771
  const apps = analysis.apps?.length ? analysis.apps : [];
8802
8772
  const context = {
8803
8773
  repoPath,
@@ -9106,7 +9076,7 @@ function buildCriteria() {
9106
9076
  impact: "medium",
9107
9077
  effort: "low",
9108
9078
  check: async (context) => {
9109
- const found = await fileExists(path8.join(context.repoPath, "CONTRIBUTING.md"));
9079
+ const found = await fileExists(path9.join(context.repoPath, "CONTRIBUTING.md"));
9110
9080
  return {
9111
9081
  status: found ? "pass" : "fail",
9112
9082
  reason: found ? void 0 : "Missing CONTRIBUTING.md for contributor workflows."
@@ -9207,7 +9177,7 @@ function buildCriteria() {
9207
9177
  impact: "high",
9208
9178
  effort: "low",
9209
9179
  check: async (context) => {
9210
- const found = await fileExists(path8.join(context.repoPath, "SECURITY.md"));
9180
+ const found = await fileExists(path9.join(context.repoPath, "SECURITY.md"));
9211
9181
  return {
9212
9182
  status: found ? "pass" : "fail",
9213
9183
  reason: found ? void 0 : "Missing SECURITY.md policy."
@@ -9223,7 +9193,7 @@ function buildCriteria() {
9223
9193
  impact: "medium",
9224
9194
  effort: "medium",
9225
9195
  check: async (context) => {
9226
- const found = await fileExists(path8.join(context.repoPath, ".github", "dependabot.yml"));
9196
+ const found = await fileExists(path9.join(context.repoPath, ".github", "dependabot.yml"));
9227
9197
  return {
9228
9198
  status: found ? "pass" : "fail",
9229
9199
  reason: found ? void 0 : "Missing .github/dependabot.yml configuration."
@@ -9429,7 +9399,7 @@ function buildCriteria() {
9429
9399
  if (area?.scripts?.build) {
9430
9400
  return { status: "pass" };
9431
9401
  }
9432
- const pkgPath = path8.join(context.areaPath, "package.json");
9402
+ const pkgPath = path9.join(context.areaPath, "package.json");
9433
9403
  const pkg = await readJson(pkgPath);
9434
9404
  const scripts = pkg?.scripts ?? {};
9435
9405
  const found = Boolean(scripts.build);
@@ -9454,7 +9424,7 @@ function buildCriteria() {
9454
9424
  if (area?.scripts?.test) {
9455
9425
  return { status: "pass" };
9456
9426
  }
9457
- const pkgPath = path8.join(context.areaPath, "package.json");
9427
+ const pkgPath = path9.join(context.areaPath, "package.json");
9458
9428
  const pkg = await readJson(pkgPath);
9459
9429
  const scripts = pkg?.scripts ?? {};
9460
9430
  const found = Boolean(scripts.test);
@@ -9477,7 +9447,7 @@ function buildCriteria() {
9477
9447
  return { status: "skip", reason: "No area context." };
9478
9448
  }
9479
9449
  const sanitized = sanitizeAreaName(area.name);
9480
- const instructionPath = path8.join(
9450
+ const instructionPath = path9.join(
9481
9451
  context.repoPath,
9482
9452
  ".github",
9483
9453
  "instructions",
@@ -9498,7 +9468,7 @@ function buildExtras() {
9498
9468
  id: "agents-doc",
9499
9469
  title: "AGENTS.md present",
9500
9470
  check: async (context) => {
9501
- const found = await fileExists(path8.join(context.repoPath, "AGENTS.md"));
9471
+ const found = await fileExists(path9.join(context.repoPath, "AGENTS.md"));
9502
9472
  return {
9503
9473
  status: found ? "pass" : "fail",
9504
9474
  reason: found ? void 0 : "Missing AGENTS.md to guide coding agents."
@@ -9663,11 +9633,11 @@ async function hasTypecheckConfig(repoPath) {
9663
9633
  ]);
9664
9634
  }
9665
9635
  async function hasGithubWorkflows(repoPath) {
9666
- return fileExists(path8.join(repoPath, ".github", "workflows"));
9636
+ return fileExists(path9.join(repoPath, ".github", "workflows"));
9667
9637
  }
9668
9638
  async function hasCodeowners(repoPath) {
9669
- const root = await fileExists(path8.join(repoPath, "CODEOWNERS"));
9670
- const github = await fileExists(path8.join(repoPath, ".github", "CODEOWNERS"));
9639
+ const root = await fileExists(path9.join(repoPath, "CODEOWNERS"));
9640
+ const github = await fileExists(path9.join(repoPath, ".github", "CODEOWNERS"));
9671
9641
  return root || github;
9672
9642
  }
9673
9643
  async function hasLicense(repoPath) {
@@ -9675,9 +9645,9 @@ async function hasLicense(repoPath) {
9675
9645
  return files.some((file) => file.toLowerCase().startsWith("license"));
9676
9646
  }
9677
9647
  async function hasPullRequestTemplate(repoPath) {
9678
- const direct = await fileExists(path8.join(repoPath, ".github", "PULL_REQUEST_TEMPLATE.md"));
9648
+ const direct = await fileExists(path9.join(repoPath, ".github", "PULL_REQUEST_TEMPLATE.md"));
9679
9649
  if (direct) return true;
9680
- const dir = path8.join(repoPath, ".github", "PULL_REQUEST_TEMPLATE");
9650
+ const dir = path9.join(repoPath, ".github", "PULL_REQUEST_TEMPLATE");
9681
9651
  try {
9682
9652
  const entries = await fs7.readdir(dir);
9683
9653
  return entries.some((entry) => entry.toLowerCase().endsWith(".md"));
@@ -9686,14 +9656,14 @@ async function hasPullRequestTemplate(repoPath) {
9686
9656
  }
9687
9657
  }
9688
9658
  async function hasPrecommitConfig(repoPath) {
9689
- const precommit = await fileExists(path8.join(repoPath, ".pre-commit-config.yaml"));
9659
+ const precommit = await fileExists(path9.join(repoPath, ".pre-commit-config.yaml"));
9690
9660
  if (precommit) return true;
9691
- return fileExists(path8.join(repoPath, ".husky"));
9661
+ return fileExists(path9.join(repoPath, ".husky"));
9692
9662
  }
9693
9663
  async function hasArchitectureDoc(repoPath) {
9694
9664
  const files = await safeReadDir(repoPath);
9695
9665
  if (files.some((file) => file.toLowerCase() === "architecture.md")) return true;
9696
- return fileExists(path8.join(repoPath, "docs", "architecture.md"));
9666
+ return fileExists(path9.join(repoPath, "docs", "architecture.md"));
9697
9667
  }
9698
9668
  async function hasCustomInstructions(repoPath) {
9699
9669
  const found = [];
@@ -9710,14 +9680,14 @@ async function hasCustomInstructions(repoPath) {
9710
9680
  "copilot-instructions.md"
9711
9681
  ];
9712
9682
  for (const candidate of candidates) {
9713
- if (await fileExists(path8.join(repoPath, candidate))) {
9683
+ if (await fileExists(path9.join(repoPath, candidate))) {
9714
9684
  found.push(candidate);
9715
9685
  }
9716
9686
  }
9717
9687
  return found;
9718
9688
  }
9719
9689
  async function hasFileBasedInstructions(repoPath) {
9720
- const instructionsDir = path8.join(repoPath, ".github", "instructions");
9690
+ const instructionsDir = path9.join(repoPath, ".github", "instructions");
9721
9691
  try {
9722
9692
  const entries = await fs7.readdir(instructionsDir);
9723
9693
  return entries.filter((e) => e.endsWith(".instructions.md")).map((e) => `.github/instructions/${e}`);
@@ -9745,7 +9715,7 @@ async function checkInstructionConsistency(repoPath, foundFiles) {
9745
9715
  }
9746
9716
  const realPathMap = /* @__PURE__ */ new Map();
9747
9717
  for (const file of foundFiles) {
9748
- const fullPath = path8.join(repoPath, file);
9718
+ const fullPath = path9.join(repoPath, file);
9749
9719
  try {
9750
9720
  const real = await fs7.realpath(fullPath);
9751
9721
  const group = realPathMap.get(real) ?? [];
@@ -9762,7 +9732,7 @@ async function checkInstructionConsistency(repoPath, foundFiles) {
9762
9732
  const contents = [];
9763
9733
  for (const group of groups) {
9764
9734
  try {
9765
- contents.push(await fs7.readFile(path8.join(repoPath, group[0]), "utf8"));
9735
+ contents.push(await fs7.readFile(path9.join(repoPath, group[0]), "utf8"));
9766
9736
  } catch {
9767
9737
  contents.push("");
9768
9738
  }
@@ -9781,17 +9751,17 @@ async function checkInstructionConsistency(repoPath, foundFiles) {
9781
9751
  }
9782
9752
  async function hasMcpConfig(repoPath) {
9783
9753
  const found = [];
9784
- if (await fileExists(path8.join(repoPath, ".vscode", "mcp.json"))) {
9754
+ if (await fileExists(path9.join(repoPath, ".vscode", "mcp.json"))) {
9785
9755
  found.push(".vscode/mcp.json");
9786
9756
  }
9787
- if (await fileExists(path8.join(repoPath, "mcp.json"))) {
9757
+ if (await fileExists(path9.join(repoPath, "mcp.json"))) {
9788
9758
  found.push("mcp.json");
9789
9759
  }
9790
- const settings = await readJson(path8.join(repoPath, ".vscode", "settings.json"));
9760
+ const settings = await readJson(path9.join(repoPath, ".vscode", "settings.json"));
9791
9761
  if (settings && (settings["mcp"] || settings["github.copilot.chat.mcp.enabled"])) {
9792
9762
  found.push(".vscode/settings.json (mcp section)");
9793
9763
  }
9794
- if (await fileExists(path8.join(repoPath, ".claude", "mcp.json"))) {
9764
+ if (await fileExists(path9.join(repoPath, ".claude", "mcp.json"))) {
9795
9765
  found.push(".claude/mcp.json");
9796
9766
  }
9797
9767
  return found;
@@ -9800,13 +9770,13 @@ async function hasCustomAgents(repoPath) {
9800
9770
  const found = [];
9801
9771
  const agentDirs = [".github/agents", ".copilot/agents", ".github/copilot/agents"];
9802
9772
  for (const dir of agentDirs) {
9803
- if (await fileExists(path8.join(repoPath, dir))) {
9773
+ if (await fileExists(path9.join(repoPath, dir))) {
9804
9774
  found.push(dir);
9805
9775
  }
9806
9776
  }
9807
9777
  const agentFiles = [".github/copilot-agents.yml", ".github/copilot-agents.yaml"];
9808
9778
  for (const agentFile of agentFiles) {
9809
- if (await fileExists(path8.join(repoPath, agentFile))) {
9779
+ if (await fileExists(path9.join(repoPath, agentFile))) {
9810
9780
  found.push(agentFile);
9811
9781
  }
9812
9782
  }
@@ -9821,7 +9791,7 @@ async function hasCopilotSkills(repoPath) {
9821
9791
  ".github/copilot/skills"
9822
9792
  ];
9823
9793
  for (const dir of skillDirs) {
9824
- if (await fileExists(path8.join(repoPath, dir))) {
9794
+ if (await fileExists(path9.join(repoPath, dir))) {
9825
9795
  found.push(dir);
9826
9796
  }
9827
9797
  }
@@ -9874,7 +9844,7 @@ async function processRepo(params) {
9874
9844
  } = params;
9875
9845
  try {
9876
9846
  progress?.update(`${label}: Cloning...`);
9877
- const cacheRoot = path9.join(process.cwd(), ".agentrc-cache");
9847
+ const cacheRoot = path10.join(process.cwd(), ".agentrc-cache");
9878
9848
  const repoPath = validateCachePath(cacheRoot, ...cacheParts);
9879
9849
  await ensureDir(repoPath);
9880
9850
  if (!await isGitRepo(repoPath)) {
@@ -9900,8 +9870,8 @@ async function processRepo(params) {
9900
9870
  if (!instructions.trim()) {
9901
9871
  throw new Error("Generated instructions were empty");
9902
9872
  }
9903
- const instructionsPath = path9.join(repoPath, ".github", "copilot-instructions.md");
9904
- await ensureDir(path9.dirname(instructionsPath));
9873
+ const instructionsPath = path10.join(repoPath, ".github", "copilot-instructions.md");
9874
+ await ensureDir(path10.dirname(instructionsPath));
9905
9875
  const { wrote, reason } = await safeWriteFile(instructionsPath, instructions, true);
9906
9876
  if (!wrote) {
9907
9877
  throw new Error(
@@ -10038,7 +10008,7 @@ async function processBatchReadinessRepo(options) {
10038
10008
  try {
10039
10009
  progress(`Cloning ${repo.fullName}...`);
10040
10010
  const authedUrl = buildAuthedUrl(repo.cloneUrl, token, "github");
10041
- await ensureDir(path9.dirname(repoDir));
10011
+ await ensureDir(path10.dirname(repoDir));
10042
10012
  await cloneRepo(authedUrl, repoDir, { shallow: true });
10043
10013
  await setRemoteUrl(repoDir, repo.cloneUrl).catch(() => {
10044
10014
  });
@@ -11088,7 +11058,7 @@ import { render as render2 } from "ink";
11088
11058
  // src/ui/BatchReadinessTui.tsx
11089
11059
  import fs8 from "fs/promises";
11090
11060
  import os from "os";
11091
- import path10 from "path";
11061
+ import path11 from "path";
11092
11062
 
11093
11063
  // packages/core/src/services/visualReport.ts
11094
11064
  function generateVisualReport(options) {
@@ -12114,7 +12084,7 @@ function BatchReadinessTui({ token, outputPath, policies }) {
12114
12084
  setStatus("processing");
12115
12085
  const selectedRepos = Array.from(selectedRepoIndices).map((i) => repos[i]);
12116
12086
  const results2 = [];
12117
- const tmpDir = path10.join(os.tmpdir(), `agentrc-batch-readiness-${Date.now()}`);
12087
+ const tmpDir = path11.join(os.tmpdir(), `agentrc-batch-readiness-${Date.now()}`);
12118
12088
  try {
12119
12089
  await ensureDir(tmpDir);
12120
12090
  for (let i = 0; i < selectedRepos.length; i++) {
@@ -12151,7 +12121,7 @@ function BatchReadinessTui({ token, outputPath, policies }) {
12151
12121
  title: "Batch Readiness Report",
12152
12122
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
12153
12123
  });
12154
- const finalOutputPath = outputPath ?? path10.join(process.cwd(), "batch-readiness-report.html");
12124
+ const finalOutputPath = outputPath ?? path11.join(process.cwd(), "batch-readiness-report.html");
12155
12125
  const { wrote, reason } = await safeWriteFile(finalOutputPath, html, true);
12156
12126
  if (!wrote) throw new Error(reason === "symlink" ? "Path is a symlink" : "Write failed");
12157
12127
  setStatus("complete");
@@ -12333,7 +12303,7 @@ async function batchReadinessCommand(options) {
12333
12303
  }
12334
12304
 
12335
12305
  // src/commands/eval.ts
12336
- import path12 from "path";
12306
+ import path13 from "path";
12337
12307
 
12338
12308
  // packages/core/src/services/evalScaffold.ts
12339
12309
  var EVAL_SCAFFOLD_TIMEOUT_MS = 6e5;
@@ -12516,17 +12486,17 @@ function normalizeEvalConfig(parsed, count) {
12516
12486
 
12517
12487
  // packages/core/src/services/evaluator.ts
12518
12488
  import fs9 from "fs/promises";
12519
- import path11 from "path";
12489
+ import path12 from "path";
12520
12490
  var DEFAULT_SYSTEM_MESSAGE = "You are answering questions about this repository. Use tools to inspect the repo and cite its files. Avoid generic Copilot CLI details unless the prompt explicitly asks for them.";
12521
12491
  async function runEval(options) {
12522
12492
  const config = await loadConfig(options.configPath);
12523
12493
  const instructionFile = config.instructionFile ?? ".github/copilot-instructions.md";
12524
- const instructionPath = path11.resolve(options.repoPath, instructionFile);
12494
+ const instructionPath = path12.resolve(options.repoPath, instructionFile);
12525
12495
  const instructionText = await readOptionalFile(instructionPath);
12526
12496
  const baseSystemMessage = config.systemMessage ?? DEFAULT_SYSTEM_MESSAGE;
12527
12497
  const progress = options.onProgress ?? (() => {
12528
12498
  });
12529
- const defaultOutputPath = path11.resolve(
12499
+ const defaultOutputPath = path12.resolve(
12530
12500
  options.repoPath,
12531
12501
  ".agentrc",
12532
12502
  "evals",
@@ -12546,9 +12516,9 @@ async function runEval(options) {
12546
12516
  const caseStartedAt = Date.now();
12547
12517
  let caseWorkingDir;
12548
12518
  if (testCase.workingDirectory) {
12549
- const resolved = path11.resolve(options.repoPath, testCase.workingDirectory);
12550
- const root = path11.resolve(options.repoPath);
12551
- if (resolved !== root && !resolved.startsWith(root + path11.sep)) {
12519
+ const resolved = path12.resolve(options.repoPath, testCase.workingDirectory);
12520
+ const root = path12.resolve(options.repoPath);
12521
+ if (resolved !== root && !resolved.startsWith(root + path12.sep)) {
12552
12522
  throw new Error(
12553
12523
  `Invalid workingDirectory "${testCase.workingDirectory}": escapes repo boundary`
12554
12524
  );
@@ -12620,7 +12590,7 @@ async function runEval(options) {
12620
12590
  };
12621
12591
  let viewerPath;
12622
12592
  if (outputPath) {
12623
- await fs9.mkdir(path11.dirname(outputPath), { recursive: true });
12593
+ await fs9.mkdir(path12.dirname(outputPath), { recursive: true });
12624
12594
  await safeWriteFile(outputPath, JSON.stringify(output, null, 2), true);
12625
12595
  viewerPath = buildViewerPath(outputPath);
12626
12596
  await safeWriteFile(viewerPath, buildTrajectoryViewerHtml(output), true);
@@ -12934,7 +12904,7 @@ function formatTokenUsage(usage) {
12934
12904
  function resolveOutputPath(repoPath, override, configValue) {
12935
12905
  const chosen = override ?? configValue;
12936
12906
  if (!chosen) return void 0;
12937
- return path11.isAbsolute(chosen) ? chosen : path11.resolve(repoPath, chosen);
12907
+ return path12.isAbsolute(chosen) ? chosen : path12.resolve(repoPath, chosen);
12938
12908
  }
12939
12909
  function buildViewerPath(outputPath) {
12940
12910
  if (outputPath.endsWith(".json")) {
@@ -13289,7 +13259,7 @@ function sanitizeValue(value, depth) {
13289
13259
 
13290
13260
  // src/commands/eval.ts
13291
13261
  async function evalCommand(configPathArg, options) {
13292
- const repoPath = path12.resolve(options.repo ?? process.cwd());
13262
+ const repoPath = path13.resolve(options.repo ?? process.cwd());
13293
13263
  if (options.listModels) {
13294
13264
  try {
13295
13265
  const models = await listCopilotModels();
@@ -13325,7 +13295,7 @@ async function evalCommand(configPathArg, options) {
13325
13295
  return;
13326
13296
  }
13327
13297
  if (options.init) {
13328
- const outputPath = path12.join(repoPath, "agentrc.eval.json");
13298
+ const outputPath = path13.join(repoPath, "agentrc.eval.json");
13329
13299
  const desiredCount = Math.max(1, Number.parseInt(options.count ?? "5", 10) || 5);
13330
13300
  try {
13331
13301
  const progress = createProgressReporter(!shouldLog(options));
@@ -13367,7 +13337,7 @@ async function evalCommand(configPathArg, options) {
13367
13337
  }
13368
13338
  return;
13369
13339
  }
13370
- const configPath = path12.resolve(configPathArg ?? path12.join(repoPath, "agentrc.eval.json"));
13340
+ const configPath = path13.resolve(configPathArg ?? path13.join(repoPath, "agentrc.eval.json"));
13371
13341
  try {
13372
13342
  const progress = createProgressReporter(!shouldLog(options));
13373
13343
  const { summary, results, viewerPath } = await runEval({
@@ -13414,30 +13384,30 @@ async function evalCommand(configPathArg, options) {
13414
13384
  }
13415
13385
 
13416
13386
  // src/commands/generate.ts
13417
- import path15 from "path";
13387
+ import path16 from "path";
13418
13388
 
13419
13389
  // packages/core/src/services/generator.ts
13420
- import path13 from "path";
13390
+ import path14 from "path";
13421
13391
  async function generateConfigs(options) {
13422
13392
  const { repoPath, analysis, selections, force } = options;
13423
13393
  const files = [];
13424
13394
  if (selections.includes("mcp")) {
13425
- const filePath = path13.join(repoPath, ".vscode", "mcp.json");
13426
- await ensureDir(path13.dirname(filePath));
13395
+ const filePath = path14.join(repoPath, ".vscode", "mcp.json");
13396
+ await ensureDir(path14.dirname(filePath));
13427
13397
  const content = renderMcp();
13428
13398
  const { wrote } = await safeWriteFile(filePath, content, force);
13429
13399
  files.push({
13430
- path: path13.relative(process.cwd(), filePath),
13400
+ path: path14.relative(process.cwd(), filePath),
13431
13401
  action: wrote ? "wrote" : "skipped"
13432
13402
  });
13433
13403
  }
13434
13404
  if (selections.includes("vscode")) {
13435
- const filePath = path13.join(repoPath, ".vscode", "settings.json");
13436
- await ensureDir(path13.dirname(filePath));
13405
+ const filePath = path14.join(repoPath, ".vscode", "settings.json");
13406
+ await ensureDir(path14.dirname(filePath));
13437
13407
  const content = renderVscodeSettings(analysis);
13438
13408
  const { wrote } = await safeWriteFile(filePath, content, force);
13439
13409
  files.push({
13440
- path: path13.relative(process.cwd(), filePath),
13410
+ path: path14.relative(process.cwd(), filePath),
13441
13411
  action: wrote ? "wrote" : "skipped"
13442
13412
  });
13443
13413
  }
@@ -13488,16 +13458,16 @@ function renderVscodeSettings(analysis) {
13488
13458
  }
13489
13459
 
13490
13460
  // src/commands/instructions.ts
13491
- import path14 from "path";
13461
+ import path15 from "path";
13492
13462
  function skipReason(action) {
13493
13463
  if (action === "symlink") return "symlink";
13494
13464
  if (action === "empty") return "empty content";
13495
13465
  return "exists, use --force";
13496
13466
  }
13497
13467
  async function instructionsCommand(options) {
13498
- const repoPath = path14.resolve(options.repo ?? process.cwd());
13499
- const outputPath = path14.resolve(
13500
- options.output ?? path14.join(repoPath, ".github", "copilot-instructions.md")
13468
+ const repoPath = path15.resolve(options.repo ?? process.cwd());
13469
+ const outputPath = path15.resolve(
13470
+ options.output ?? path15.join(repoPath, ".github", "copilot-instructions.md")
13501
13471
  );
13502
13472
  const progress = createProgressReporter(!shouldLog(options));
13503
13473
  const wantAreas = options.areas || options.areasOnly || options.area;
@@ -13544,7 +13514,7 @@ async function instructionsCommand(options) {
13544
13514
  ] : []
13545
13515
  ];
13546
13516
  for (const file of dryFiles) {
13547
- const relPath = path14.relative(process.cwd(), path14.join(repoPath, file.path));
13517
+ const relPath = path15.relative(process.cwd(), path15.join(repoPath, file.path));
13548
13518
  if (shouldLog(options)) {
13549
13519
  progress.update(
13550
13520
  `[dry-run] Would write ${relPath} (${Buffer.byteLength(file.content, "utf8")} bytes)`
@@ -13565,7 +13535,7 @@ async function instructionsCommand(options) {
13565
13535
  } else {
13566
13536
  const actions = await writeNestedInstructions(repoPath, nestedResult, options.force);
13567
13537
  for (const action of actions) {
13568
- const relPath = path14.relative(process.cwd(), action.path);
13538
+ const relPath = path15.relative(process.cwd(), action.path);
13569
13539
  if (action.action === "wrote") {
13570
13540
  if (shouldLog(options)) progress.succeed(`Wrote ${relPath}`);
13571
13541
  } else if (shouldLog(options)) {
@@ -13608,8 +13578,8 @@ async function instructionsCommand(options) {
13608
13578
  }
13609
13579
  if (content) {
13610
13580
  if (options.dryRun) {
13611
- const relPath = path14.relative(repoPath, outputPath);
13612
- const displayPath = path14.relative(process.cwd(), outputPath);
13581
+ const relPath = path15.relative(repoPath, outputPath);
13582
+ const displayPath = path15.relative(process.cwd(), outputPath);
13613
13583
  const byteCount = Buffer.byteLength(content, "utf8");
13614
13584
  if (shouldLog(options)) {
13615
13585
  progress.update(`[dry-run] Would write ${displayPath} (${byteCount} bytes)`);
@@ -13618,14 +13588,14 @@ async function instructionsCommand(options) {
13618
13588
  dryRunFiles.push({ path: relPath, bytes: byteCount });
13619
13589
  }
13620
13590
  } else {
13621
- await ensureDir(path14.dirname(outputPath));
13591
+ await ensureDir(path15.dirname(outputPath));
13622
13592
  const { wrote, reason } = await safeWriteFile(
13623
13593
  outputPath,
13624
13594
  content,
13625
13595
  Boolean(options.force)
13626
13596
  );
13627
13597
  if (!wrote) {
13628
- const relPath = path14.relative(process.cwd(), outputPath);
13598
+ const relPath = path15.relative(process.cwd(), outputPath);
13629
13599
  const why = reason === "symlink" ? "path is a symlink" : "file exists (use --force)";
13630
13600
  if (options.json) {
13631
13601
  const result = {
@@ -13647,7 +13617,7 @@ async function instructionsCommand(options) {
13647
13617
  };
13648
13618
  outputResult(result, true);
13649
13619
  } else if (shouldLog(options)) {
13650
- progress.succeed(`Updated ${path14.relative(process.cwd(), outputPath)}`);
13620
+ progress.succeed(`Updated ${path15.relative(process.cwd(), outputPath)}`);
13651
13621
  }
13652
13622
  }
13653
13623
  }
@@ -13714,7 +13684,7 @@ async function instructionsCommand(options) {
13714
13684
  ] : []
13715
13685
  ];
13716
13686
  for (const file of dryFiles) {
13717
- const relPath = path14.relative(process.cwd(), path14.join(repoPath, file.path));
13687
+ const relPath = path15.relative(process.cwd(), path15.join(repoPath, file.path));
13718
13688
  if (shouldLog(options)) {
13719
13689
  progress.update(
13720
13690
  `[dry-run] Would write ${relPath} (${Buffer.byteLength(file.content, "utf8")} bytes)`
@@ -13732,7 +13702,7 @@ async function instructionsCommand(options) {
13732
13702
  } else {
13733
13703
  const actions = await writeNestedInstructions(repoPath, nestedResult, options.force);
13734
13704
  for (const action of actions) {
13735
- const relPath = path14.relative(process.cwd(), action.path);
13705
+ const relPath = path15.relative(process.cwd(), action.path);
13736
13706
  if (action.action === "wrote") {
13737
13707
  if (shouldLog(options)) progress.succeed(`Wrote ${relPath}`);
13738
13708
  } else if (shouldLog(options)) {
@@ -13764,7 +13734,7 @@ async function instructionsCommand(options) {
13764
13734
  }
13765
13735
  if (options.json) {
13766
13736
  dryRunFiles.push({
13767
- path: path14.relative(repoPath, areaInstructionPath(repoPath, area)),
13737
+ path: path15.relative(repoPath, areaInstructionPath(repoPath, area)),
13768
13738
  bytes: Buffer.byteLength(body, "utf8")
13769
13739
  });
13770
13740
  }
@@ -13785,7 +13755,7 @@ async function instructionsCommand(options) {
13785
13755
  continue;
13786
13756
  }
13787
13757
  if (shouldLog(options)) {
13788
- progress.succeed(`Wrote ${path14.relative(process.cwd(), result.filePath)}`);
13758
+ progress.succeed(`Wrote ${path15.relative(process.cwd(), result.filePath)}`);
13789
13759
  }
13790
13760
  }
13791
13761
  }
@@ -13820,7 +13790,7 @@ async function instructionsCommand(options) {
13820
13790
 
13821
13791
  // src/commands/generate.ts
13822
13792
  async function generateCommand(type, repoPathArg, options) {
13823
- const repoPath = path15.resolve(repoPathArg ?? process.cwd());
13793
+ const repoPath = path16.resolve(repoPathArg ?? process.cwd());
13824
13794
  if (type === "instructions" || type === "agents") {
13825
13795
  if (!options.quiet) {
13826
13796
  process.stderr.write(
@@ -13834,7 +13804,7 @@ async function generateCommand(type, repoPathArg, options) {
13834
13804
  `
13835
13805
  );
13836
13806
  }
13837
- const output = type === "agents" ? path15.join(repoPath, "AGENTS.md") : void 0;
13807
+ const output = type === "agents" ? path16.join(repoPath, "AGENTS.md") : void 0;
13838
13808
  await instructionsCommand({
13839
13809
  repo: repoPath,
13840
13810
  output,
@@ -13896,10 +13866,37 @@ async function generateCommand(type, repoPathArg, options) {
13896
13866
  }
13897
13867
 
13898
13868
  // src/commands/init.ts
13899
- import path16 from "path";
13869
+ import path18 from "path";
13870
+
13871
+ // packages/core/src/services/configScaffold.ts
13872
+ import path17 from "path";
13873
+ async function scaffoldAgentrcConfig(repoPath, areas, force = false) {
13874
+ if (areas.length === 0) return null;
13875
+ const configPath = path17.join(repoPath, "agentrc.config.json");
13876
+ const workspaces = await detectWorkspaces(repoPath, areas);
13877
+ const workspacePaths = workspaces.map((ws) => ws.path + "/");
13878
+ const standaloneAreas = areas.filter((a) => {
13879
+ if (!a.path) return true;
13880
+ const rel = path17.relative(repoPath, a.path).replace(/\\/gu, "/");
13881
+ return !workspacePaths.some((prefix) => rel.startsWith(prefix));
13882
+ }).map((a) => ({
13883
+ name: a.name,
13884
+ applyTo: a.applyTo,
13885
+ ...a.description ? { description: a.description } : {}
13886
+ }));
13887
+ const agentrcConfig = {};
13888
+ if (workspaces.length > 0) agentrcConfig.workspaces = workspaces;
13889
+ if (standaloneAreas.length > 0) agentrcConfig.areas = standaloneAreas;
13890
+ if (!agentrcConfig.workspaces && !agentrcConfig.areas) return null;
13891
+ const configContent = JSON.stringify(agentrcConfig, null, 2) + "\n";
13892
+ const { wrote } = await safeWriteFile(configPath, configContent, force);
13893
+ return { wrote, configPath };
13894
+ }
13895
+
13896
+ // src/commands/init.ts
13900
13897
  import { checkbox, select } from "@inquirer/prompts";
13901
13898
  async function initCommand(repoPathArg, options) {
13902
- let repoPath = path16.resolve(repoPathArg ?? process.cwd());
13899
+ let repoPath = path18.resolve(repoPathArg ?? process.cwd());
13903
13900
  const provider = options.provider ?? (options.github ? "github" : void 0);
13904
13901
  if (provider && provider !== "github" && provider !== "azure") {
13905
13902
  outputError("Invalid provider. Use github or azure.", Boolean(options.json));
@@ -13937,7 +13934,7 @@ async function initCommand(repoPathArg, options) {
13937
13934
  value: repo
13938
13935
  }))
13939
13936
  });
13940
- const cacheRoot = path16.join(process.cwd(), ".agentrc-cache");
13937
+ const cacheRoot = path18.join(process.cwd(), ".agentrc-cache");
13941
13938
  repoPath = validateCachePath(cacheRoot, selection.owner, selection.name);
13942
13939
  await ensureDir(repoPath);
13943
13940
  const hasGit = await isGitRepo(repoPath);
@@ -13990,7 +13987,7 @@ async function initCommand(repoPathArg, options) {
13990
13987
  value: repo
13991
13988
  }))
13992
13989
  });
13993
- const cacheRoot = path16.join(process.cwd(), ".agentrc-cache");
13990
+ const cacheRoot = path18.join(process.cwd(), ".agentrc-cache");
13994
13991
  repoPath = validateCachePath(
13995
13992
  cacheRoot,
13996
13993
  orgSelection.name,
@@ -14029,17 +14026,17 @@ async function initCommand(repoPathArg, options) {
14029
14026
  });
14030
14027
  const allFiles = [];
14031
14028
  if (selections.includes("instructions")) {
14032
- const outputPath = path16.join(repoPath, ".github", "copilot-instructions.md");
14033
- await ensureDir(path16.dirname(outputPath));
14029
+ const outputPath = path18.join(repoPath, ".github", "copilot-instructions.md");
14030
+ await ensureDir(path18.dirname(outputPath));
14034
14031
  try {
14035
14032
  const content = await generateCopilotInstructions({ repoPath, model: options.model });
14036
14033
  const { wrote } = await safeWriteFile(outputPath, content, Boolean(options.force));
14037
14034
  allFiles.push({
14038
- path: path16.relative(process.cwd(), outputPath),
14035
+ path: path18.relative(process.cwd(), outputPath),
14039
14036
  action: wrote ? "wrote" : "skipped"
14040
14037
  });
14041
14038
  if (shouldLog(options)) {
14042
- const rel = path16.relative(process.cwd(), outputPath);
14039
+ const rel = path18.relative(process.cwd(), outputPath);
14043
14040
  process.stderr.write((wrote ? `Wrote ${rel}` : `Skipped ${rel} (exists)`) + "\n");
14044
14041
  }
14045
14042
  } catch (error) {
@@ -14067,28 +14064,12 @@ async function initCommand(repoPathArg, options) {
14067
14064
  }
14068
14065
  allFiles.push(...genResult.files);
14069
14066
  if (analysis.areas && analysis.areas.length > 0) {
14070
- const configPath = path16.join(repoPath, "agentrc.config.json");
14071
- const workspaces = await detectWorkspaces(repoPath, analysis.areas);
14072
- const workspacePaths = workspaces.map((ws) => ws.path + "/");
14073
- const standaloneAreas = analysis.areas.filter((a) => {
14074
- if (!a.path) return true;
14075
- const rel = path16.relative(repoPath, a.path).replace(/\\/gu, "/");
14076
- return !workspacePaths.some((prefix) => rel.startsWith(prefix));
14077
- }).map((a) => ({
14078
- name: a.name,
14079
- applyTo: a.applyTo,
14080
- ...a.description ? { description: a.description } : {}
14081
- }));
14082
- const agentrcConfig = {};
14083
- if (workspaces.length > 0) agentrcConfig.workspaces = workspaces;
14084
- if (standaloneAreas.length > 0) agentrcConfig.areas = standaloneAreas;
14085
- if (agentrcConfig.workspaces || agentrcConfig.areas) {
14086
- const configContent = JSON.stringify(agentrcConfig, null, 2) + "\n";
14087
- const { wrote } = await safeWriteFile(configPath, configContent, Boolean(options.force));
14088
- const rel = path16.relative(process.cwd(), configPath);
14089
- allFiles.push({ path: rel, action: wrote ? "wrote" : "skipped" });
14067
+ const result = await scaffoldAgentrcConfig(repoPath, analysis.areas, Boolean(options.force));
14068
+ if (result) {
14069
+ const rel = path18.relative(process.cwd(), result.configPath);
14070
+ allFiles.push({ path: rel, action: result.wrote ? "wrote" : "skipped" });
14090
14071
  if (shouldLog(options)) {
14091
- process.stderr.write((wrote ? `Wrote ${rel}` : `Skipped ${rel} (exists)`) + "\n");
14072
+ process.stderr.write((result.wrote ? `Wrote ${rel}` : `Skipped ${rel} (exists)`) + "\n");
14092
14073
  }
14093
14074
  }
14094
14075
  }
@@ -14115,7 +14096,7 @@ async function initCommand(repoPathArg, options) {
14115
14096
  }
14116
14097
 
14117
14098
  // src/commands/pr.ts
14118
- import path17 from "path";
14099
+ import path19 from "path";
14119
14100
  var DEFAULT_PR_BRANCH = "agentrc/add-ai-config";
14120
14101
  async function prCommand(repo, options) {
14121
14102
  const provider = options.provider ?? "github";
@@ -14149,7 +14130,7 @@ async function prCommand(repo, options) {
14149
14130
  try {
14150
14131
  progress.update("Fetching repo info...");
14151
14132
  const repoInfo = await getRepo(token2, organization, project, name2);
14152
- const cacheRoot = path17.join(process.cwd(), ".agentrc-cache");
14133
+ const cacheRoot = path19.join(process.cwd(), ".agentrc-cache");
14153
14134
  const repoPath = validateCachePath(cacheRoot, organization, project, name2);
14154
14135
  await ensureDir(repoPath);
14155
14136
  if (!await isGitRepo(repoPath)) {
@@ -14163,8 +14144,8 @@ async function prCommand(repo, options) {
14163
14144
  await checkoutBranch(repoPath, branch);
14164
14145
  progress.update("Generating instructions...");
14165
14146
  const instructions = await generateCopilotInstructions({ repoPath, model: options.model });
14166
- const instructionsPath = path17.join(repoPath, ".github", "copilot-instructions.md");
14167
- await ensureDir(path17.dirname(instructionsPath));
14147
+ const instructionsPath = path19.join(repoPath, ".github", "copilot-instructions.md");
14148
+ await ensureDir(path19.dirname(instructionsPath));
14168
14149
  const { wrote, reason } = await safeWriteFile(instructionsPath, instructions, true);
14169
14150
  if (!wrote) {
14170
14151
  throw new Error(
@@ -14231,7 +14212,7 @@ async function prCommand(repo, options) {
14231
14212
  try {
14232
14213
  progress.update("Fetching repo info...");
14233
14214
  const repoInfo = await getRepo2(token, owner, name);
14234
- const cacheRoot = path17.join(process.cwd(), ".agentrc-cache");
14215
+ const cacheRoot = path19.join(process.cwd(), ".agentrc-cache");
14235
14216
  const repoPath = validateCachePath(cacheRoot, owner, name);
14236
14217
  await ensureDir(repoPath);
14237
14218
  if (!await isGitRepo(repoPath)) {
@@ -14243,8 +14224,8 @@ async function prCommand(repo, options) {
14243
14224
  await checkoutBranch(repoPath, branch);
14244
14225
  progress.update("Generating instructions...");
14245
14226
  const instructions = await generateCopilotInstructions({ repoPath, model: options.model });
14246
- const instructionsPath = path17.join(repoPath, ".github", "copilot-instructions.md");
14247
- await ensureDir(path17.dirname(instructionsPath));
14227
+ const instructionsPath = path19.join(repoPath, ".github", "copilot-instructions.md");
14228
+ await ensureDir(path19.dirname(instructionsPath));
14248
14229
  const { wrote, reason } = await safeWriteFile(instructionsPath, instructions, true);
14249
14230
  if (!wrote) {
14250
14231
  throw new Error(
@@ -14293,13 +14274,13 @@ async function prCommand(repo, options) {
14293
14274
  }
14294
14275
 
14295
14276
  // src/commands/readiness.ts
14296
- import path18 from "path";
14277
+ import path20 from "path";
14297
14278
  import chalk3 from "chalk";
14298
14279
  async function readinessCommand(repoPathArg, options) {
14299
- const repoPath = path18.resolve(repoPathArg ?? process.cwd());
14300
- const repoName = path18.basename(repoPath);
14301
- const resolvedOutputPath = options.output ? path18.resolve(options.output) : "";
14302
- const outputExt = options.output ? path18.extname(options.output).toLowerCase() : "";
14280
+ const repoPath = path20.resolve(repoPathArg ?? process.cwd());
14281
+ const repoName = path20.basename(repoPath);
14282
+ const resolvedOutputPath = options.output ? path20.resolve(options.output) : "";
14283
+ const outputExt = options.output ? path20.extname(options.output).toLowerCase() : "";
14303
14284
  let failLevelError;
14304
14285
  let report;
14305
14286
  try {
@@ -14361,7 +14342,7 @@ async function readinessCommand(repoPathArg, options) {
14361
14342
  title: `Readiness Report: ${repoName}`,
14362
14343
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
14363
14344
  });
14364
- const outputPath = options.output ? resolvedOutputPath : path18.join(repoPath, "readiness-report.html");
14345
+ const outputPath = options.output ? resolvedOutputPath : path20.join(repoPath, "readiness-report.html");
14365
14346
  const { wrote, reason } = await safeWriteFile(outputPath, html, Boolean(options.force));
14366
14347
  if (!wrote) {
14367
14348
  const why = reason === "symlink" ? "path is a symlink" : "file exists (use --force)";
@@ -14596,26 +14577,32 @@ function formatReadinessMarkdown(report, repoName) {
14596
14577
  }
14597
14578
 
14598
14579
  // src/commands/tui.tsx
14599
- import path20 from "path";
14580
+ import path22 from "path";
14600
14581
  import { render as render3 } from "ink";
14601
14582
 
14602
14583
  // src/ui/tui.tsx
14603
14584
  import fs10 from "fs/promises";
14604
- import path19 from "path";
14585
+ import path21 from "path";
14605
14586
  import { Box as Box5, Text as Text5, useApp as useApp4, useInput as useInput4, useStdout, useIsScreenReaderEnabled as useIsScreenReaderEnabled5 } from "ink";
14606
14587
  import { useEffect as useEffect5, useMemo, useState as useState5 } from "react";
14607
14588
  import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
14608
14589
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
14609
14590
  function useTerminalColumns() {
14610
14591
  const { stdout } = useStdout();
14592
+ const accessible = useIsScreenReaderEnabled5();
14611
14593
  const [columns, setColumns] = useState5(stdout.columns ?? 80);
14612
14594
  useEffect5(() => {
14613
- const onResize = () => setColumns(stdout.columns ?? 80);
14614
- stdout.on("resize", onResize);
14595
+ const onResize = () => {
14596
+ if (!accessible) {
14597
+ stdout.write("\x1B[2J\x1B[H");
14598
+ }
14599
+ setColumns(stdout.columns ?? 80);
14600
+ };
14601
+ stdout.prependListener("resize", onResize);
14615
14602
  return () => {
14616
14603
  stdout.off("resize", onResize);
14617
14604
  };
14618
- }, [stdout]);
14605
+ }, [stdout, accessible]);
14619
14606
  return columns;
14620
14607
  }
14621
14608
  function useSpinner(active) {
@@ -14700,6 +14687,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14700
14687
  const [modelPickTarget, setModelPickTarget] = useState5("eval");
14701
14688
  const [modelCursor, setModelCursor] = useState5(0);
14702
14689
  const [hasEvalConfig, setHasEvalConfig] = useState5(null);
14690
+ const [hasAgentrcConfig, setHasAgentrcConfig] = useState5(null);
14703
14691
  const [activityLog, setActivityLog] = useState5([]);
14704
14692
  const [generateTarget, setGenerateTarget] = useState5(
14705
14693
  "copilot-instructions"
@@ -14709,7 +14697,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14709
14697
  const [isMonorepo, setIsMonorepo] = useState5(false);
14710
14698
  const [repoAreas, setRepoAreas] = useState5([]);
14711
14699
  const [areaCursor, setAreaCursor] = useState5(0);
14712
- const repoLabel = useMemo(() => path19.basename(repoPath), [repoPath]);
14700
+ const repoLabel = useMemo(() => path21.basename(repoPath), [repoPath]);
14713
14701
  const repoFull = useMemo(() => repoPath, [repoPath]);
14714
14702
  const isLoading = status === "generating" || status === "bootstrapping" || status === "evaluating" || status === "generating-areas" || status === "readiness-running";
14715
14703
  const isMenu = status === "model-pick" || status === "eval-pick" || status === "batch-pick" || status === "generate-pick" || status === "generate-app-pick" || status === "generate-area-pick";
@@ -14721,14 +14709,24 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14721
14709
  setStatus("idle");
14722
14710
  };
14723
14711
  useEffect5(() => {
14724
- const configPath = path19.join(repoPath, "agentrc.eval.json");
14712
+ const configPath = path21.join(repoPath, "agentrc.eval.json");
14725
14713
  fs10.access(configPath).then(() => setHasEvalConfig(true)).catch(() => setHasEvalConfig(false));
14714
+ const agentrcConfigCandidates = [
14715
+ path21.join(repoPath, "agentrc.config.json"),
14716
+ path21.join(repoPath, ".github", "agentrc.config.json")
14717
+ ];
14718
+ Promise.all(
14719
+ agentrcConfigCandidates.map(
14720
+ (p) => fs10.access(p).then(() => true).catch(() => false)
14721
+ )
14722
+ ).then((results) => setHasAgentrcConfig(results.some(Boolean))).catch(() => setHasAgentrcConfig(false));
14726
14723
  analyzeRepo(repoPath).then((analysis) => {
14727
14724
  const apps = analysis.apps ?? [];
14728
14725
  setRepoApps(apps);
14729
14726
  setIsMonorepo(analysis.isMonorepo ?? false);
14730
14727
  setRepoAreas(analysis.areas ?? []);
14731
14728
  }).catch((err) => {
14729
+ setRepoAreas([]);
14732
14730
  addLog(`Repo analysis failed: ${err instanceof Error ? err.message : "unknown"}`, "error");
14733
14731
  });
14734
14732
  }, [repoPath]);
@@ -14782,7 +14780,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14782
14780
  };
14783
14781
  useEffect5(() => {
14784
14782
  let active = true;
14785
- const configPath = path19.join(repoPath, "agentrc.eval.json");
14783
+ const configPath = path21.join(repoPath, "agentrc.eval.json");
14786
14784
  fs10.readFile(configPath, "utf8").then((raw) => {
14787
14785
  if (!active) return;
14788
14786
  const parsed = JSON.parse(raw);
@@ -14797,7 +14795,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14797
14795
  };
14798
14796
  }, [repoPath]);
14799
14797
  const bootstrapEvalConfig = async (count, force) => {
14800
- const configPath = path19.join(repoPath, "agentrc.eval.json");
14798
+ const configPath = path21.join(repoPath, "agentrc.eval.json");
14801
14799
  try {
14802
14800
  setStatus("bootstrapping");
14803
14801
  setMessage("Generating eval cases with Copilot SDK...");
@@ -14836,13 +14834,13 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14836
14834
  if (status === "preview") {
14837
14835
  if (input.toLowerCase() === "s") {
14838
14836
  try {
14839
- const outputPath = generateSavePath || path19.join(repoPath, ".github", "copilot-instructions.md");
14840
- await fs10.mkdir(path19.dirname(outputPath), { recursive: true });
14837
+ const outputPath = generateSavePath || path21.join(repoPath, ".github", "copilot-instructions.md");
14838
+ await fs10.mkdir(path21.dirname(outputPath), { recursive: true });
14841
14839
  const { wrote, reason } = await safeWriteFile(outputPath, generatedContent, true);
14842
14840
  if (!wrote)
14843
14841
  throw new Error(reason === "symlink" ? "Path is a symlink" : "Write failed");
14844
14842
  setStatus("done");
14845
- const relPath = path19.relative(repoPath, outputPath);
14843
+ const relPath = path21.relative(repoPath, outputPath);
14846
14844
  const msg = `Saved to ${relPath}`;
14847
14845
  setMessage(msg);
14848
14846
  addLog(msg, "success");
@@ -14876,7 +14874,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14876
14874
  setMessage("Enter a positive number of eval cases, then press Enter.");
14877
14875
  return;
14878
14876
  }
14879
- const configPath = path19.join(repoPath, "agentrc.eval.json");
14877
+ const configPath = path21.join(repoPath, "agentrc.eval.json");
14880
14878
  setEvalBootstrapCount(count);
14881
14879
  try {
14882
14880
  await fs10.access(configPath);
@@ -14935,7 +14933,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14935
14933
  setStatus("generate-app-pick");
14936
14934
  setMessage("Generate for root or per-app?");
14937
14935
  } else {
14938
- const savePath = path19.join(repoPath, ".github", "copilot-instructions.md");
14936
+ const savePath = path21.join(repoPath, ".github", "copilot-instructions.md");
14939
14937
  setGenerateSavePath(savePath);
14940
14938
  await doGenerate(repoPath, savePath, "copilot-instructions");
14941
14939
  }
@@ -14947,7 +14945,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14947
14945
  setStatus("generate-app-pick");
14948
14946
  setMessage("Generate for root or per-app?");
14949
14947
  } else {
14950
- const savePath = path19.join(repoPath, "AGENTS.md");
14948
+ const savePath = path21.join(repoPath, "AGENTS.md");
14951
14949
  setGenerateSavePath(savePath);
14952
14950
  await doGenerate(repoPath, savePath, "agents-md");
14953
14951
  }
@@ -14972,7 +14970,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14972
14970
  }
14973
14971
  if (status === "generate-app-pick") {
14974
14972
  if (input.toLowerCase() === "r") {
14975
- const savePath = generateTarget === "copilot-instructions" ? path19.join(repoPath, ".github", "copilot-instructions.md") : path19.join(repoPath, "AGENTS.md");
14973
+ const savePath = generateTarget === "copilot-instructions" ? path21.join(repoPath, ".github", "copilot-instructions.md") : path21.join(repoPath, "AGENTS.md");
14976
14974
  setGenerateSavePath(savePath);
14977
14975
  await doGenerate(repoPath, savePath, generateTarget);
14978
14976
  return;
@@ -14982,7 +14980,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14982
14980
  addLog(`Generating ${generateTarget} for ${repoApps.length} apps...`, "progress");
14983
14981
  let count = 0;
14984
14982
  for (const app2 of repoApps) {
14985
- const savePath = generateTarget === "copilot-instructions" ? path19.join(app2.path, ".github", "copilot-instructions.md") : path19.join(app2.path, "AGENTS.md");
14983
+ const savePath = generateTarget === "copilot-instructions" ? path21.join(app2.path, ".github", "copilot-instructions.md") : path21.join(app2.path, "AGENTS.md");
14986
14984
  setMessage(`Generating for ${app2.name} (${count + 1}/${repoApps.length})...`);
14987
14985
  try {
14988
14986
  const content = await generateCopilotInstructions({
@@ -14990,11 +14988,11 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
14990
14988
  onProgress: (msg) => setMessage(`${app2.name}: ${msg}`)
14991
14989
  });
14992
14990
  if (content.trim()) {
14993
- await fs10.mkdir(path19.dirname(savePath), { recursive: true });
14991
+ await fs10.mkdir(path21.dirname(savePath), { recursive: true });
14994
14992
  const { wrote: saved } = await safeWriteFile(savePath, content, true);
14995
14993
  if (!saved) continue;
14996
14994
  count++;
14997
- addLog(`${app2.name}: saved ${path19.basename(savePath)}`, "success");
14995
+ addLog(`${app2.name}: saved ${path21.basename(savePath)}`, "success");
14998
14996
  }
14999
14997
  } catch (error) {
15000
14998
  const msg = error instanceof Error ? error.message : "Failed.";
@@ -15008,7 +15006,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15008
15006
  const num = Number.parseInt(input, 10);
15009
15007
  if (Number.isFinite(num) && num >= 1 && num <= repoApps.length) {
15010
15008
  const app2 = repoApps[num - 1];
15011
- const savePath = generateTarget === "copilot-instructions" ? path19.join(app2.path, ".github", "copilot-instructions.md") : path19.join(app2.path, "AGENTS.md");
15009
+ const savePath = generateTarget === "copilot-instructions" ? path21.join(app2.path, ".github", "copilot-instructions.md") : path21.join(app2.path, "AGENTS.md");
15012
15010
  setGenerateSavePath(savePath);
15013
15011
  await doGenerate(app2.path, savePath, generateTarget);
15014
15012
  return;
@@ -15036,7 +15034,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15036
15034
  const result = await writeAreaInstruction(repoPath, area, body);
15037
15035
  if (result.status === "written") {
15038
15036
  written++;
15039
- addLog(`${area.name}: saved ${path19.basename(result.filePath)}`, "success");
15037
+ addLog(`${area.name}: saved ${path21.basename(result.filePath)}`, "success");
15040
15038
  } else if (result.status === "skipped") {
15041
15039
  addLog(`${area.name}: skipped (file exists)`, "info");
15042
15040
  }
@@ -15130,8 +15128,8 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15130
15128
  }
15131
15129
  if (status === "eval-pick") {
15132
15130
  if (input.toLowerCase() === "r") {
15133
- const configPath = path19.join(repoPath, "agentrc.eval.json");
15134
- const outputPath = path19.join(
15131
+ const configPath = path21.join(repoPath, "agentrc.eval.json");
15132
+ const outputPath = path21.join(
15135
15133
  repoPath,
15136
15134
  ".agentrc",
15137
15135
  "evals",
@@ -15275,6 +15273,44 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15275
15273
  setMessage("Select eval action.");
15276
15274
  return;
15277
15275
  }
15276
+ if (input.toLowerCase() === "c") {
15277
+ if (hasAgentrcConfig) {
15278
+ setMessage("agentrc.config.json already exists.");
15279
+ return;
15280
+ }
15281
+ if (repoAreas.length === 0) {
15282
+ setMessage("No areas detected. Cannot scaffold agentrc.config.json.");
15283
+ return;
15284
+ }
15285
+ setStatus("generating");
15286
+ setMessage("Creating agentrc.config.json...");
15287
+ addLog("Scaffolding agentrc.config.json...", "progress");
15288
+ try {
15289
+ const result = await scaffoldAgentrcConfig(repoPath, repoAreas);
15290
+ if (!result) {
15291
+ setStatus("idle");
15292
+ setMessage("Nothing to scaffold \u2014 no areas or workspaces detected.");
15293
+ addLog("No areas to scaffold into config.", "info");
15294
+ } else if (result.wrote) {
15295
+ setHasAgentrcConfig(true);
15296
+ setStatus("done");
15297
+ const msg = `Created agentrc.config.json`;
15298
+ setMessage(msg);
15299
+ addLog(msg, "success");
15300
+ } else {
15301
+ setHasAgentrcConfig(true);
15302
+ setStatus("idle");
15303
+ setMessage("agentrc.config.json already exists (skipped).");
15304
+ addLog("agentrc.config.json already exists.", "info");
15305
+ }
15306
+ } catch (error) {
15307
+ setStatus("error");
15308
+ const msg = error instanceof Error ? error.message : "Failed to create config.";
15309
+ setMessage(msg);
15310
+ addLog(msg, "error");
15311
+ }
15312
+ return;
15313
+ }
15278
15314
  if (input.toLowerCase() === "m") {
15279
15315
  if (hideModelPicker) {
15280
15316
  setMessage(
@@ -15389,6 +15425,10 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15389
15425
  /* @__PURE__ */ jsxs4(Text5, { children: [
15390
15426
  /* @__PURE__ */ jsx7(Text5, { color: "gray", children: "Eval " }),
15391
15427
  hasEvalConfig === null ? /* @__PURE__ */ jsx7(Text5, { color: "gray", dimColor: true, children: "checking..." }) : hasEvalConfig ? /* @__PURE__ */ jsx7(Text5, { color: "green", children: "agentrc.eval.json found" }) : /* @__PURE__ */ jsx7(Text5, { color: "yellow", children: "no eval config \u2014 press [I] to create" })
15428
+ ] }),
15429
+ /* @__PURE__ */ jsxs4(Text5, { children: [
15430
+ /* @__PURE__ */ jsx7(Text5, { color: "gray", children: "Config " }),
15431
+ hasAgentrcConfig === null ? /* @__PURE__ */ jsx7(Text5, { color: "gray", dimColor: true, children: "checking..." }) : hasAgentrcConfig ? /* @__PURE__ */ jsx7(Text5, { color: "green", children: "agentrc.config.json found" }) : /* @__PURE__ */ jsx7(Text5, { color: "yellow", children: "no config \u2014 press [C] to create" })
15392
15432
  ] })
15393
15433
  ] }),
15394
15434
  /* @__PURE__ */ jsx7(Divider, { columns: terminalColumns, label: "Activity", accessible }),
@@ -15464,7 +15504,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15464
15504
  /* @__PURE__ */ jsx7(Text5, { color: "white", children: app2.name }),
15465
15505
  /* @__PURE__ */ jsxs4(Text5, { color: "gray", dimColor: true, children: [
15466
15506
  " ",
15467
- path19.relative(repoPath, app2.path)
15507
+ path21.relative(repoPath, app2.path)
15468
15508
  ] })
15469
15509
  ] }, app2.name)) })
15470
15510
  ] }),
@@ -15498,7 +15538,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15498
15538
  children: [
15499
15539
  /* @__PURE__ */ jsxs4(Text5, { color: "cyan", bold: true, children: [
15500
15540
  "Preview (",
15501
- path19.relative(repoPath, generateSavePath) || generateTarget,
15541
+ path21.relative(repoPath, generateSavePath) || generateTarget,
15502
15542
  ")"
15503
15543
  ] }),
15504
15544
  /* @__PURE__ */ jsx7(Text5, { color: "gray", children: truncatedPreview })
@@ -15595,6 +15635,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15595
15635
  /* @__PURE__ */ jsxs4(Box5, { children: [
15596
15636
  /* @__PURE__ */ jsx7(KeyHint, { k: "M", label: "Model" }),
15597
15637
  /* @__PURE__ */ jsx7(KeyHint, { k: "J", label: "Judge" }),
15638
+ hasAgentrcConfig === false && /* @__PURE__ */ jsx7(KeyHint, { k: "C", label: "Create config" }),
15598
15639
  /* @__PURE__ */ jsx7(KeyHint, { k: "Q", label: "Quit" })
15599
15640
  ] })
15600
15641
  ] }) })
@@ -15606,7 +15647,7 @@ function AgentRCTui({ repoPath, skipAnimation = false }) {
15606
15647
  // src/commands/tui.tsx
15607
15648
  import { jsx as jsx8 } from "react/jsx-runtime";
15608
15649
  async function tuiCommand(options) {
15609
- const repoPath = path20.resolve(options.repo ?? process.cwd());
15650
+ const repoPath = path22.resolve(options.repo ?? process.cwd());
15610
15651
  const skipAnimation = options.animation === false;
15611
15652
  try {
15612
15653
  const accessible = options.accessible ? true : void 0;