Как я обнаружил, что система управления разработкой и реальное состояние кода расходятся — и почему при AI-assisted разработке недостаточно просто выполнять задачи: нужно постоянно сверять систему с реальностью.

В AI-assisted development легко построить систему, которая выглядит очень организованной.

Есть task queue. Есть generated prompts. Есть статусы:

ready
prompt_generated
completed
blocked

Есть roadmap, completion reports и история commits.

Проблема возникает, когда все эти источники начинают описывать разные версии реальности.

Именно с этим я столкнулся, используя один repository как control plane для разработки, а второй — как actual implementation.

В какой-то момент control plane говорил примерно следующее:

latest completed task = 006DWO
006DWP = prompt_generated

Но implementation repository говорил другое:

006DWP implemented
006DWP committed
006DWP pushed to master

Причём это была не незакоммиченная локальная работа. Для 006DWP существовала полноценная commit lineage:

50155d2...
aa7daef...
d13a01f...

Последний commit уже находился в system-v2/master.

То есть обе системы по отдельности выглядели исправными.

Но вместе они больше не описывали одну и ту же систему.

Что представлял собой control plane

Архитектура сознательно разделяла orchestration и implementation:

ai-dev-platform
      ↓
 task specification
 generated prompt
 task state
 completion metadata
 roadmap
      ↓
system-v2
 actual implementation
 tests
 reports
 commits

Control-plane agent отвечал за sequencing, task specs, generated prompts, queue state и governance.

При этом ему прямо запрещалось самостоятельно реализовывать изменения в target repository. Target-repo changes должны были проходить через явный task/workflow record.

Такое разделение было полезным: agent, управляющий работой, не должен одновременно незаметно менять систему, которой он управляет.

Но появляется другая проблема.

Control plane имеет собственное состояние.

Repository имеет собственное состояние.

И эти два состояния могут разойтись.

Как возник drift

Для нескольких предыдущих tasks состояние совпадало:

006DWN → completed
006DWO → completed

Implementation присутствовала, commits были известны, control plane содержал completion metadata.

Для 006DWP цепочка оборвалась.

Control plane содержал:

task spec: yes
generated prompt: yes
status: prompt_generated
completion metadata: no

А implementation repository уже содержал:

implementation: yes
tests/report: yes
commits: yes
pushed master: yes

Roadmap при этом по-прежнему утверждал, что latest verified synchronization заканчивается на 006DWO.

Хуже того, в том же roadmap оставались ещё более старые sections, описывавшие состояние repository до нескольких последующих изменений.

Получался документ, где несколько исторических состояний системы одновременно выглядели текущими.

Почему это опаснее обычной stale documentation

Если устарел README, это обычно неприятность.

Если устарел control plane, он начинает принимать решения на неверной модели мира.

Например, orchestration layer мог считать текущим blocker:

operator_gated_redacted_the_jwt_validation_artifact_required...

Но actual implementation уже продвинулось дальше.

Реальный следующий blocker находился в другом месте:

existing_corpus_replay_not_executed

То есть проблема была не только в неправильном status label.

Менялась последовательность следующей работы.

AI agent, доверившийся control plane без проверки, мог начать решать уже не текущую проблему.

Нельзя просто объявить repository единственным источником истины

На первый взгляд решение простое:

Если документация и код расходятся — верь коду.

Но этого тоже недостаточно.

Repository может доказать, что implementation существует.

Он не обязательно доказывает:

  • что task прошёл требуемую validation;
  • что report относится именно к этому commit;
  • что результат был merged по правильной процедуре;
  • что evidence соответствует заявленному уровню;
  • что следующий task уже разрешён governance layer.

В случае 006DWP implementation была реальной, но её evidence имела строго ограниченный смысл:

evidence class = deterministic_fixture
real corpus replay executed = false
corpus rows replayed = 0

Поэтому правильным выводом было не:

006DWP proves the mechanism in reality

а:

006DWP implementation exists
fixture mechanism proof exists
real corpus replay is still missing

Это важное различие.

Code truth и evidence truth — не одно и то же.

Я перестал искать один source of truth

Практически полезнее оказалось думать не об одном authoritative file, а о нескольких независимых слоях truth:

task ledger
    ↓
generated task specification
    ↓
repository state
    ↓
commit history
    ↓
test/report artifacts
    ↓
evidence classification

Если они согласованы — можно двигаться дальше.

Если нет — система должна перейти в reconciliation.

То есть перед следующим task нужно ответить хотя бы на четыре вопроса:

Что control plane считает сделанным?

Что реально находится в master?

Какие artifacts доказывают результат?

Что эти artifacts на самом деле позволяют утверждать?

Это уже не task execution.

Это state reconciliation.

Reconciliation вместо догадки

В данном случае audit дал довольно чёткую картину.

Что было доказано:

system-v2/master contains 006DWP
implementation is committed and pushed
both repositories are clean
fixture proof exists

Что не было доказано:

real corpus replay executed
functionality proven
execution readiness proven
real-life functionality proven

И отдельно:

control plane completion state is stale

После такого разделения следующий шаг становился простым.

Не нужно было повторно реализовывать 006DWP.

Не нужно было перескакивать к live execution.

Нужно было сначала синхронизировать control-plane ledger с implementation reality, а затем продолжить с реального blocker.

Почему AI делает эту проблему заметнее

Человек, долго работающий над одним repository, часто помнит, что происходило вчера.

AI agent такого устойчивого operational memory не имеет.

Он каждый раз реконструирует состояние системы из доступного context:

tasks
roadmap
reports
git state
prompts
handoffs

Если эти источники расходятся, хороший language model не устраняет фундаментальную проблему.

Наоборот, чем убедительнее модель умеет объяснять найденную информацию, тем опаснее stale state.

Она может построить очень логичный plan на неверной исходной модели.

Поэтому для AI-assisted engineering я теперь считаю reconciliation частью control plane, а не housekeeping.

Какой pattern оказался рабочим

Перед созданием следующего implementation task полезно делать небольшой reality check:

control-plane task state
        ↕
target repository master
        ↕
commit / report evidence
        ↕
current blocker

Если есть mismatch:

STOP TASK GENERATION
        ↓
RECONCILE
        ↓
CLASSIFY WHAT IS PROVEN
        ↓
UPDATE CONTROL STATE
        ↓
ONLY THEN SELECT NEXT TASK

Это дешевле, чем позволить нескольким AI agents продолжать работу от разных версий истории.

Несколько правил, которые я из этого вынес

Control plane не становится truth только потому, что он называется control plane.

Его состояние тоже нужно проверять.

Code presence не равно completion.

Нужны tests, reports, lineage и правильная evidence classification.

Documentation drift в agentic system — operational defect.

Если от неё зависит task selection, это уже не косметическая проблема.

Не смешивать implementation truth и evidence truth.

Код может существовать, а доказательство его поведения оставаться fixture-only.

Следующий task нельзя выбирать до reconciliation.

Иначе AI может очень эффективно решить неправильную проблему.

Stale state должен уменьшать authority системы, а не увеличивать уверенность ответа.

Если источники расходятся, правильная реакция — не выбрать самый удобный из них, а явно зафиксировать disagreement.

Итог

Главный урок оказался довольно простым.

AI-assisted development system — это не только механизм:

plan → prompt → code → test

Нужен ещё один цикл:

observe reality
      ↓
compare with control state
      ↓
reconcile disagreement
      ↓
update authoritative state
      ↓
continue

В моём случае один repository говорил, что 006DWP всё ещё только prompt_generated.

Другой уже содержал три связанных commits и завершённую implementation.

При этом evidence всё ещё оставалась fixture-only, а real corpus replay содержал:

0 rows

Ни один из этих фактов нельзя было отбросить.

Нужно было сохранить их все и восстановить согласованную картину.

Для agentic development это и есть одна из основных функций control plane:

не только управлять работой, но и регулярно проверять, что его собственная версия реальности всё ещё соответствует реальности.