План локального ремонта
Согласованное решение
Явный --owned-checkout у check-prerequisites, finalize-tasks и spec-commit. Только single_branch; остальные формы с новым флагом отклоняются. Без флага поведение остаётся прежним. Глобальная установка и публикация патча не входят в этап; обезличенный Windows defect зарегистрирован в https://github.com/Priivacy-ai/spec-kitty/issues/3822 .
Архитектура
Общая проверка команд использует resolve_ownership_claim, штатный resolver идентификаторов, target branch и protection policy обоих корней. Canonical primary остаётся Git identity, effective root задаёт место документов. Для явного режима проекции размещения используют существующий mission_context_for(..., effective_root=...). Статусный bootstrap передаёт проверенный корень в чтение и transactional emitter, не пишет события самостоятельно. Пустой или неподдерживаемый контекст отказывается до любой записи.
Проверки
Красный CLI тест через существующий entrypoint до патча; затем явный режим проверки, validate-only, commit и финализации. Матрица: чужой/вложенный/повреждённый корень; одинаковый slug; отсутствие метаданных; protected/detached/mismatched ветка; смешанная пачка путей и ссылки наружу; чужой index; повтор без дубликатов. Primary и второй worktree сравниваются по содержимому, index и refs. Дополнительно затронутые resolver/status/commit тесты, Ruff и проверка типов. Независимый reviewer читает фиксированный diff; родитель повторяет ключевые тесты.
Доказательства и риски
На исходном 33710617b проверка и validate-only не находят документы внешнего worktree. Проверки ownership дали 20 passed и 1 fixture failure. Последний повторён отдельно: PermissionError при записи тестового .git. Минимальное исправление fixture сохраняет повреждение указателя и assertions.
Существующего генератора карты нет. Перед кодом подготовлена локальная карта фактических вызовов в docs/codemap; при изменениях обновляются JSON, HTML и lock. Штатная финализация документации заблокирована исправляемой ошибкой, поэтому приёмка до успешного исправления не объявляется. Исходные разрешения и независимый архитектурный разбор получены до начала этого этапа.
Локальное расширение приёмки
Согласовано 2026-08-31: добавить accept --owned-checkout через существующий resolve_owned_mission. Проверенный корень явно передаётся через чтение, проверку матрицы и сохранение; глобального контекста или второго resolver не будет. Область затрагивает команду, её библиотеку приёмки, контекст матрицы и существующее размещение артефактов. Изменения нужны потому, что эти вызовы повторно выбирают primary независимо от корня входной команды.
Порядок: красный интеграционный тест, передача контекста, положительные и отрицательные тесты, независимое чтение фиксированного diff и диагностика реальной исходной задачи без записи. Существующие тесты трёх команд и приёмки повторяются. Временные HOME и runtime задаются до импорта Python; корневой CLI с настоящим пользовательским окружением не запускается. Кодировка в диагностическом режиме не исправляется. Глобальная доставка и формальный переход реальной задачи отдельно.
Уточнение по реальному тесту записи: завершающий перенос статусов также повторно выбирает primary. Требование FR-009 уже включает эту запись; проверенное владение передаётся через существующие функции переноса и проверки статусов до записи итоговой отметки. До первой записи проверяются оба каталога. Общий canonicalizer, хранилище событий, reducer и поведение миграций без явного контекста не меняются.
Проект ремонта смены статуса
Цель дополнения: одна команда move-task и её непосредственные пути чтения, проверки и записи. Подробные требования: FR-011..FR-015, SC-009..SC-012. Код до согласования этого дополнения не меняется; установка и публикация исключены.
Точка входа и контекст
Добавить необязательный --owned-checkout в существующий Typer entrypoint. Использовать resolve_owned_mission и передавать полученный неизменяемый контекст в существующую командную структуру аргументов/состояния, без нового глобального контекста, monkeypatch, второго resolver или переопределения Git identity. Корневой checkout остаётся идентичностью репозитория; effective root обозначает место выбранных документов и служебного состояния, target обозначает ветку commit.
В обычном пути без флага оставить прежние вызовы. В явном пути проводить контекст через границы, которые действительно снова выбирают корневой checkout: tasks_shared, tasks_move_task, tasks_verdict_persistence, рабочий контекст, поиск пакета работы и цикл ревью. Статусные транзакции и writer артефактов уже поддерживают effective_root; использовать их, а не писать события напрямую. Дополнительные записи назначения/возврата также должны сохранить контекст.
Проверка реализации
Не подменять ResolvedWorkspace.resolution_kind на repo_root: это пропускает проверку рабочей копии. Не использовать ветку назначения как базу diff, когда она совпадает с HEAD. Сначала проверить существующую декларацию базы и штатный Git resolver, затем получить конкретную пригодную ревизию сравнения. При отсутствии однозначной базы отказаться до перехода, требующего проверки реализации или актуальности ревью. Начальное назначение и обычный возврат не получают нового требования базы. Декларация разрешается в commit и merge-base того же репозитория; конфликт, неразрешимая ссылка и сравнение с HEAD дают отказ. Одна ревизия фиксируется на весь запуск для diff и проверки implementation commit. Новое эвристическое угадывание и автоматическое исправление planning metadata не входят в ремонт.
Сохранить обычные проверки подзадач, наличия implementation commit, diff scope, актуальности ревью, статуса и защищённой ветки. При --owned-checkout отклонять недоказанные режимы из FR-015 до любой записи, не отключая их без флага.
Проверки и последовательность
Сначала дополнить фактическую карту вызовов: текущая docs/codemap/codemap.lock привязана к b98c0f76c и не описывает move-task. Перед изменением кода обновить JSON, HTML и lock вместе. Затем отдельным commit добавить красный тест через tasks.app: локальные документы есть, команда без исправления ищет другую копию. После этого провести явный контекст, не меняя reducer или формат событий.
Один последовательный пакет реализации: общий контекст и его consumers нельзя раздать параллельным writers. Обязателен последующий независимый review точного diff и повтор ключевых проверок основной сессией. Техническая база уже содержит проверенный accept и writer матрицы; их контракт повторно не проектируется. Новые подзадачи расширяют существующий пакет последовательно; формальная приёмка вынесена из его подзадач в завершающую проверку после одобрения. Прежнее техническое ревью не выдаётся за ревью будущего дополнения.
Целевые проверки: новый реальный Git CLI тест, существующие test_tasks_move_task_cwd.py, test_move_task_guard.py, test_move_task_approval_evidence.py, test_move_task_durability.py, test_tasks_compat_surface.py, test_tasks_transition_core.py, интеграционные тесты явного корня и затронутые проверки workspace/review/transaction. Имена будут зафиксированы с точными путями в пакете реализации. Ruff, mypy, неизменность соседних копий и значимая мутация дополняют, а не заменяют эти тесты.
Все проверки запускаются из исходного модуля с отдельными HOME и runtime, до импорта Python. Сеть и пользовательские credential-файлы не используются. Корневой CLI с настоящим HOME, глобальный upgrade и реальные переходы исходного навыка не являются проверочным стендом.
Риски и границы
Это больше, чем добавление одного параметра: забытый повторный выбор корня может дать ложный diff или направить вторичную запись в другую копию. Положительный тест должен пройти до настоящего review commit; имитации ports/writers не служат единственным доказательством. Минимальные прямые dependencies уточняются аудитом. Если обычные проверки требуют ещё одной команды или нового формата metadata, остановиться и показать изменение объёма, не расширять ремонт скрытно.
Проект ремонта отметки подзадач
Контекст и размещение
Typer-wrapper получает необязательный --owned-checkout и передаёт его в _do_mark_status. Состояние команды хранит OwnedMission; проверка выполняется через resolve_owned_mission до чтения mission. Для всех read/write legs используется один MissionHandle(primary, slug, effective_root=owned.root). Существующие RealFsReader и RealCoordCommitRouter уже умеют проводить effective_root; новый resolver и ambient environment override не нужны.
tasks.md и authored roster читаются через TASKS_INDEX placement выбранной копии. STATUS_STATE placement той же копии задаёт event и snapshot paths. Общий lock остаётся под Git common dir, поэтому primary и linked worktree синхронизируются одним штатным lock без переноса данных между ними.
Запись и побочные эффекты
Обычный путь сохраняет emit_inner_state_changed. Owned-путь использует уже существующий emit_inner_state_changed_transactional(..., effective_root=...), который применяет BookkeepingTransaction, общий Git lock, verified append, materialize и commit без fallback. Отдельный commit_artifact(STATUS_STATE) не нужен и не добавляется. --no-auto-commit и active sync отклоняются до записи.
Глобальные emit_history_added, emit_error_logged и dossier sync не имеют explicit-root контракта. В owned-режиме они не вызываются, как уже сделано для ambient error writer в move-task; canonical subtask event остаётся полной локальной записью. Обычный режим сохраняет существующий порядок и seams. Если event уже durable, а commit не удался, команда возвращает ненулевой структурированный результат с state_applied=true, event ID, applied WP, destination и фактическим dirty-state, не выдавая частичный результат за чистый успех. Batch группируется по WP как сейчас; каждая WP-группа выполняется одной последовательной транзакцией. При позднем сбое ответ перечисляет уже применённые WP/event IDs и не утверждает атомарность всего batch. Materialization/readback failure также является ошибкой: stale status.json не считается успехом.
Последовательность и проверки
1. Обновить JSON, HTML и lock карты: Typer entrypoint вызывает tasks_mark_status; команда затрагивает placement, status emit/store/reducer, commit-router и ambient sync hooks. Зафиксировать отдельный RED через реальный CLI на синтетических primary, selected и sibling. 2. Провести OwnedMission и MissionHandle.effective_root через state и reads; добавить ранние refusal/flagless tests. В owned-пути передать тот же root в transactional annotation writer вместо обычного emitter. 3. Проверить batch done, обратный pending, несколько WP, ошибочные roots/branches/index, active sync, no-auto-commit, transaction, materialization/readback failure, одинаковый slug и отсутствие изменений primary/sibling. Повторить contract, seam, status и compatibility наборы; выполнить содержательные мутации root и event path. 4. Провести независимое ревью точного diff и повторить ключевые тесты основной сессией. Только после этого новым CLI записать завершение подзадач и продолжить canonical lifecycle WP01.
Целевые существующие проверки: test_tasks_mark_status.py, test_tasks_mark_status_seam.py, test_tasks_cli_contract.py, test_tasks_compat_surface.py, test_infer_subtasks_primary.py, test_issue_2684_subtask_completion_event_sourced.py и новый integration-файл owned-режима. Дополнительно: Ruff, mypy с отдельным учётом прежних ошибок, git diff --check и hashes карты.
Границы
Один последовательный writer: новые изменения пересекают wrapper, orchestration state и status commit path. Не менять глобальные sync emitters, status schema, reducer или contracts других команд ради удобства этого ремонта. Любая такая необходимость является material delta и возвращается на согласование.