# TRACEABILITY — стандарт маркеров-трассировки `ORCH-NNN` (golden source трассировки) > **Назначение.** Единый нормативный контракт: как нетривиальная строка/блок/инвариант в коде > привязывается к work item, который его ввёл, и к его архитектурному решению (ADR). Это **слой 4 > (трассировка)** эпика **ORCH-52** — рядом с `PIPELINE_DOCS.md` (слой 1, структура документов) и > `HANDOFF_PROTOCOL.md` (слой 2, машинный frontmatter-контракт). > > **Статус истины.** Документ **кодифицирует сложившуюся практику**, а не вводит новый синтаксис. > Источник истины о *поведении* остаётся код (`src/stages.py`, `src/qg/checks.py`, > `src/stage_engine.py`); этот стандарт — описательно-нормативный, **не машинный гейт конвейера**. > Соблюдение держится на дисциплине агентов + оси ревью (`reviewer.md`), а не на CI-lint. Введён задачей **ORCH-078** (ORCH-52e). Сквозной ADR: [`docs/architecture/adr/adr-0022-traceability-marker-standard.md`](../architecture/adr/adr-0022-traceability-marker-standard.md); детально — `docs/work-items/ORCH-078/06-adr/ADR-001-traceability-marker-standard.md`. Продолжает цепочку стандартов эпика 52: adr-0019 (52b), adr-0020 (52c), adr-0021 (52d). --- ## 1. Назначение и определение **Маркер `ORCH-NNN`** (а для проекта enduro-trails — `ET-NNN`) в коде = обязательный стандарт трассировки: он привязывает нетривиальную строку / блок / инвариант к work item, который его ввёл, и к его ADR. Это даёт читающему агенту прямой путь «строка кода → решение, которое её породило», вместо `git blame`-археологии. **Факт (сверено на 2026-06-09):** в `src/` де-факто живёт **51 уникальный** маркер `ORCH-NNN` (`grep -rhoE 'ORCH-[0-9]+' src/ | sort -u | wc -l` → `51`) — сложившаяся практика. Этот стандарт её формализует. **Массовый ретро-фит существующих 51 маркера вне объёма** — стандарт нормативен «на будущее»: его правила применяются к **новому и правимому** коду. --- ## 2. Формат маркера Маркер — это **inline-комментарий** (или фрагмент docstring модуля/функции), содержащий идентификатор work item `ORCH-NNN`. Рекомендуется рядом указывать ссылку на конкретное решение в ADR, чтобы трасса вела не просто к задаче, а к пункту решения: ```python # Ordering term — ``t2.id < jobs.task_id`` (FIFO, ORCH-088, ADR-001 D1 / FR-2): a task # does not enter `analysis` while an earlier unfinished task exists in the same repo. ``` Нового синтаксиса не вводится — кодифицируется уже сложившийся стиль (`ORCH-NNN[, ADR-001 D1]`). --- ## 3. Где ставится маркер Маркер ставится рядом с **нетривиальным инвариантом**, понимание которого требует контекста решения: - выбор fail-open / fail-closed поведения; - точное условие сериализации / упорядочивания (FIFO, lease, барьер); - идемпотентность / защита от повторной обработки; - обходимая «дыра» конвейера, которую блок закрывает; - любое условие, чьё «почему именно так» зафиксировано в ADR. Маркер **НЕ ставится** на тривиальном/самоочевидном коде (геттеры, простые присваивания, очевидные проверки) — это только зашумляет. **Правило для нового кода:** вводишь значимый инвариант → ставь маркер своей задачи (`ORCH-NNN`) рядом, по возможности со ссылкой на пункт ADR. --- ## 4. Как читать историю (с реальным проверяемым примером) Пошагово, от строки кода к решению: 1. Видишь в коде маркер `ORCH-NNN` у строки/блока, который собираешься менять. 2. Открываешь его архитектурное решение: `docs/work-items/ORCH-NNN/06-adr/`. 3. Читаешь зафиксированный инвариант ПЕРЕД правкой; не ломаешь его (см. §7). **Проверяемый пример из реального кода (`main`):** > `src/serial_gate.py` несёт условие сериализации `t2.id < jobs.task_id` с маркером **ORCH-088** > и отсылкой `ADR-001 D1 / FR-2` (FIFO-уточнение serial-gate). Чтобы понять, почему задача не входит > в `analysis`, пока в репо есть более ранняя незавершённая задача, читаешь: > `docs/work-items/ORCH-088/06-adr/ADR-001-serial-gate.md`. Пример ссылается на **реально существующие** в `main` файл и ADR — иначе стандарт опровергал бы сам себя (нерабочая трассировка). --- ## 5. Fallback-доступ к чужому ADR Папки `docs/work-items/ORCH-NNN/` может **не быть в текущей ветке** (она срезана от `main` без неё — типично для ветки другой задачи). Штатный способ прочитать чужой ADR — взять его из `origin/main`: ```bash git fetch origin # при необходимости заранее git ls-tree origin/main:docs/work-items/ORCH-NNN/06-adr/ # листинг доступных ADR git show origin/main:docs/work-items/ORCH-NNN/06-adr/ADR-001-.md # прочитать конкретный ``` Это не блокер: отсутствие папки в ветке ≠ отсутствие решения — оно всегда есть в `main`. --- ## 6. Анти-археология: 3+ маркеров → сводный сквозной ADR Если функция/блок несёт **3+** маркеров `ORCH-NNN` (эволюционировал через много задач), раскопки по каждому work item нечитаемы. Вместо перечисления всех задач ставится **одна сводная ссылка на сквозной ADR** (`docs/architecture/adr/adr-NNNN-*`), агрегирующий эволюцию. Числовой порог `3` — граница, за которой inline-перечисление перестаёт быть читаемым (один-два маркера ещё информативны, три и больше — уже археология). **Пример из кода:** `src/merge_gate.py` несёт маркеры ORCH-043/065/071/073 (и ещё несколько) → читать сводные сквозные `adr-0006` (merge-gate), `adr-0013` (merge-verify-gate), `adr-0014` (sha-source-of-truth), `adr-0016` (ensure-open-PR) в `docs/architecture/adr/`, а не 8 отдельных work item. Это конвенция для **нового/правимого** блока; массовая переразметка существующих файлов вне объёма. --- ## 7. Правило чтения (каноничная формулировка — единый источник) Это **единственное** место, где живёт каноничный текст правила. Промпты агентов (`developer.md`/`architect.md`/`reviewer.md`) **ссылаются** на него, а не копируют — чтобы не было дрейфа формулировок между файлами. > **Правишь код с маркером `ORCH-NNN` → прочитай его `docs/work-items/ORCH-NNN/06-adr/` ПЕРЕД > изменением; не сломай зафиксированный инвариант. Не можешь сохранить инвариант — эскалируй / > верни задачу в анализ, не правь вслепую.** Папки нет в ветке → читай из `origin/main` (§5). Блок > несёт 3+ маркеров → опирайся на сводный сквозной ADR (§6). Кто и как применяет правило: - **developer / architect** — обязаны выполнить чтение ПЕРЕД правкой маркированного кода. - **architect** — при введении/правке блока с 3+ маркерами оформляет/обновляет сводный сквозной ADR. - **reviewer** — проверяет соблюдение: правка маркированного (`ORCH-NNN`) кода без сверки с его ADR или со сломом инварианта → finding (рекомендуемая severity **P1**; слом критического инварианта конвейера — на усмотрение reviewer вплоть до P0). --- ## Связи - Сквозной ADR: [`adr-0022`](../architecture/adr/adr-0022-traceability-marker-standard.md). - Стандарты-соседи: [`PIPELINE_DOCS.md`](PIPELINE_DOCS.md) (слой 1), [`HANDOFF_PROTOCOL.md`](HANDOFF_PROTOCOL.md) (слой 2). - Цепочка эпика 52: adr-0019 (52b) / adr-0020 (52c) / adr-0021 (52d) / adr-0022 (52e). - Прецедент класса ошибки (слом инварианта без чтения ADR): `docs/history/LESSONS_2026-06-08_phantom-merge.md`.