Перейти к содержанию

Параллельная работа без конфликтов файлов

Параллельные агенты полезны, когда работа действительно разделяется на самостоятельные области. Простое увеличение числа исполнителей не делает задачу быстрее, если все правят одну функцию и опираются на разные версии требований. В этом уроке распределим работу над нашей библиотекой по файлам и определим роль интегратора. Результатом будет понятный договор передачи, позволяющий объединить изменения без неявной конкуренции за исходники.

Мы рассматриваем авторскую схему, а не запускаем новые учебные агенты из примера. Файл lanes.json описывает области: код, редакционные документы и карточка ревью. Манифест и правила остаются общими входами только для чтения. Такая организация связана с текущей задачей рекомендуемого отбора. В более крупной серии параллельно можно писать разные уроки или независимые модули, но общие интерфейсы должны быть определены заранее.

Разделение по ответственности

Исполнитель кода владеет catalog.py. Он реализует выбранную функцию и сохраняет формат краткого результата. Редакционный исполнитель уточняет описание входа и диагностического случая в TASK.md и DIAGNOSIS.md. Интегратор читает оба результата и пишет REVIEW.md. Это разные файлы и разные обязанности. При такой схеме редактор не исправляет функцию «заодно», а автор кода не переписывает критерий принятия, чтобы его решение выглядело подходящим.

Общие документы требуют отдельного отношения. Если в процессе выяснилось, что manifest.json не соответствует контракту, исполнитель сообщает проблему интегратору, но не меняет источник сам. Иначе параллельные результаты могут опираться на разные входные данные. Один автор рассмотрит public: false, другой уже увидит public: true; оба будут рассуждать последовательно, но объединение станет противоречивым. Поэтому общая основа фиксируется до распределения, а изменения основы согласуются как отдельное действие.

Разделение по функциям внутри одного файла возможно, но сложнее для небольшой задачи. Два исполнителя могут независимо менять импорт, форматирование или общий основной блок. Даже если логические обязанности различны, текстовый конфликт всё равно появится. Для нашей библиотеки выгоднее оставить одного владельца программы и параллельно готовить документы. Реальная скорость зависит от независимости работ, а не от числа сообщений «начал выполнение» в интерфейсе.

Контракт передачи

Каждый исполнитель получает входное состояние, свой результат, принадлежащие пути и запреты. Слово «напиши документацию» недостаточно: нужно указать, какое поведение уже задано и какие утверждения ещё не проверены. Редактор не должен изображать успешный запуск, если автор кода его не выполнял. Исполнитель кода также не получает разрешение расширить функцию только потому, что редактор предложил полезную идею. Передача основана на фактах и действующем поручении.

Полезно записывать состояние результата в коротком сообщении: какие файлы готовы, что изменено и какие ограничения остались. Это сообщение помогает интегратору выбрать следующий шаг, но не заменяет чтение файлов. В нашей серии архивные карточки не являются реальными ответами вызванных агентов. При настоящей работе сохраните фактические сообщения отдельно и отличайте их от итогового редакционного описания, которое могло быть написано позже.

Если исполнители работают в общей директории, изменения видны сразу. Это требует дисциплины владения: нельзя незаметно переписать чужой файл после прочитанного замечания. Если нужны независимые варианты одного кода, используйте отдельные рабочие состояния и явно выберите вариант при интеграции. Конкретные средства Git помогают хранить изменения, но наличие веток не устраняет противоречие требований. Текст без конфликтных маркеров ещё не означает согласованную программу.

Работа интегратора

Интегратор сопоставляет интерфейс и смысл. Функция должна принимать массив записей и лимит; карточка задачи должна описывать тот же диапазон; диагностический документ должен отличать авторский случай от наблюдения. Если редактор пишет «принимается любой числовой тип», а код принимает только обычный int, возникает семантический конфликт. Он может не затронуть одинаковые строки и пройти текстовое слияние незаметно. Поэтому интеграция требует чтения договоров, а не только механического объединения.

Для нашего проекта существенны четыре общих свойства: адрес берётся из манифеста, private исключается, featured является boolean, лимит имеет точный тип. Исполнители могут по-разному объяснять эти свойства, но не должны менять их смысл. Когда интегратор находит расхождение, замечание адресуется конкретному владельцу с указанием файла и результата. Так исправление возвращается в нужную область, а не превращается в неконтролируемую коллективную правку всех документов.

Не все этапы стоит выполнять параллельно. Ревью окончательного кандидата зависит от появления этого кандидата. Диагностическое сообщение о конкретной ошибке зависит от понятного механизма ошибки. Можно заранее готовить структуру документов и общие условия, но фактические утверждения следует заполнять после получения результата. Параллельная работа экономит время на независимых частях; она не отменяет причинную последовательность зависимых действий.

Ожидаемый результат чтения lanes.json — у каждого изменяемого файла один владелец, общие входы защищены договором, интегратор отвечает за согласование. В учебном примере не выполнялись команды слияния и не запускались программы. Поэтому схема показывает способ организации, а не измеренную эффективность команды. В реальном проекте полезно оценить также стоимость передачи: если объяснение задачи занимает больше времени, чем её выполнение, дополнительный агент может не помочь.

Завершение одной области раньше другой

Допустим, автор кода завершил функцию, а редактор ещё уточняет диагностику. Интегратор может читать стабильный файл программы и готовить замечания, но не должен объявлять весь пакет окончательным. Состояние передачи по областям точнее общего «готово». Оно показывает, какой результат уже доступен и от чего зависит завершение. Если файлы продолжают меняться, время чтения также имеет значение для конкретного замечания.

Когда редактор закончит, интегратор сопоставит описанный тип лимита с финальным кодом. Если автор программы после замечания изменил условие, карточку нужно читать заново в этой точке, а не полагаться на ранее увиденную строку. Это обычная зависимость результатов, которую параллельность не отменяет. Инструменты сообщений помогают координации, но фактические файлы остаются предметом интеграции.

Для независимых уроков распределение обычно шире: каждый автор получает свою серию, а общий интегратор обновляет каталог. Такая схема сохраняет одного владельца глобальных файлов и позволяет писать много материалов без конфликтов. В нашей маленькой лаборатории тот же принцип проявляется на нескольких документах: общая основа одна, а области записи явно различаются.

Следующий урок добавит бюджет. Параллельные исполнители могут быстрее расходовать доступные ресурсы, особенно при повторном чтении большого контекста. Мы будем учитывать каждый вызов по явным исходным данным и отделять учебный расчёт от реального тарифного отчёта. Это позволит обсуждать скорость вместе с ценой и границей следующей попытки.

Полный файл lanes.json из состояния lesson-10. Полное самостоятельное состояние находится в архиве серии; фрагмент не заменяет остальные определения.

{
  "code": [
    "catalog.py"
  ],
  "editorial": [
    "TASK.md",
    "DIAGNOSIS.md"
  ],
  "integrator": [
    "REVIEW.md"
  ],
  "shared_contract": [
    "manifest.json",
    "RULES.md"
  ],
  "merge_policy": "owners edit only own paths; integrator checks interface statically"
}

Статус примера: not_run. При подготовке не выполнялись учебные программы, тесты, вызовы AI или деплой. Описанные эффекты ожидаемые.

Оглавление серии · Полные исходники

Первичные документы: Источник 1.