Глава 5

Отделяйте исследование от редактирования

На неизвестной кодовой базе первый результат агента должен быть картой решения, а не patch. Плановый или read-only режим снижает риск исправить симптом не в том слое и создаёт проверяемое основание для изменений. В companion-проекте это буквально отдельный шаг: сначала ограниченная индексация репозитория, и только потом запись.

TypeScript
export async function indexRepository(rootInput: string, options: IndexOptions): Promise<RepositoryMap> {
  if (options.maxFiles < 1 || options.maxBytesPerFile < 0) {
    throw new Error("Index limits must be positive");
  }
  const root = await canonicalRoot(rootInput);
  const entries: RepositoryEntry[] = [];
  let totalBytes = 0;
  let truncated = false;

  async function visit(directory: string): Promise<void> {
    const children = await readdir(directory, { withFileTypes: true });
    children.sort((left, right) => left.name.localeCompare(right.name));
    for (const child of children) {
      if (entries.length >= options.maxFiles) {
        truncated = true;
        return;
      }
      if (ignoredNames.has(child.name)) {
        continue;
      }
      const absolutePath = join(directory, child.name);
      if (child.isSymbolicLink()) {
        continue;
      }
      if (child.isDirectory()) {
        await visit(absolutePath);
        if (truncated) {
          return;
        }
        continue;
      }
      if (!child.isFile()) {
        continue;
      }
      await resolveExistingContained(root, absolutePath);
      const fileStats = await stat(absolutePath);
      const relativePath = normalizeRelativePath(relative(root, absolutePath));
      entries.push({
        path: relativePath,
        bytes: Math.min(fileStats.size, options.maxBytesPerFile),
        kind: classify(relativePath)
      });
      totalBytes += fileStats.size;
    }
  }

  await visit(root);
  return { root, entries, totalBytes, truncated };

Индексатор намеренно ограничен - он не идёт по symbolic links, сортирует детерминированно и обрывается по лимиту файлов и байтов.

Исследуй дефект, но пока не меняй файлы.
Найди entry point, вызываемые функции, тесты и локальные инструкции.
Покажи фактический путь данных с file:symbol.
Отдели наблюдаемые факты от гипотез.
В конце предложи минимальный write scope и команды проверки.

Исследовательский проход должен вернуть не пересказ, а конкретику: точку входа и публичный контракт, файлы и символы, реально участвующие в поведении, путь данных от входа до эффекта, существующие тесты и ближайший аналог, команды проверки и неопределённости, которые меняют дизайн. Запрос для такого режима формулируется продукт-независимо: "исследуй дефект, но пока не меняй файлы; покажи фактический путь данных с file:symbol; отдели наблюдаемые факты от гипотез; в конце предложи минимальный write scope".

И оговорка, которая экономит время.

Маленькая задача не требует церемонии. Официальные рекомендации Claude Code прямо отмечают overhead планирования. Для очевидной опечатки или однострочной замены достаточно точного промпта и проверки diff. План нужен, когда путь решения или scope неочевидны.

Исследование дало карту. Следующий шаг - план, который можно отклонить до того, как появится хоть один patch.

Проверка знаний

Почему на незнакомой базе первый результат должен быть картой, а не patch?

Ссылки