Намеренные пробелы, открытые дефекты и что вне области
Три разных вещи, которые до этой страницы выглядели одинаково: «мы решили этого не делать», «мы это не доделали» и «это сломано». Сторож, чьё слепое пятно не объявлено, читается как полный — поэтому пробелы объявлены здесь, а не выведены читателем из тишины.
Признак намеренного пробела — названная причина, почему закрыть его сейчас дороже, чем жить с ним. Запись без такой причины не пробел, а дефект, и её место в задачах. Поэтому у каждой строки ниже есть и причина, и ссылка на то, что держит границу.
Намеренные пробелы
Каждая запись отвечает на один вопрос: что именно НЕ гарантировано — не «работает частично», а что проедет мимо и в каком случае.
Гейт маршрутизации знаний не видит игнорируемый приёмник
Не гарантировано: запись знания в файл, который игнорируется git, не будет остановлена на закрытии задачи или коммите. Так же не виден путь вне репозитория (~/.claude/**/memory/).
Почему живём: входом гейта служит git status --porcelain, и --ignored затянул бы в него .tausik/, node_modules/ и каждый артефакт сборки. Игнорируемый файл до коммита всё равно не доходит, а утечку в него ловит другой слой — хук PreToolUse. Вопрос гейта — «несёт ли изменение, которое проект сейчас записывает, знание за его пределы», вопрос хука — «утекает ли эта запись», и только второй видит игнорируемый путь.
Держит границу: докстринг scripts/gate_memory_route.py (оба предела названы там же, где код), tests/test_memory_sinks.py.
Гейт размера файла смотрит только на файлы задачи
Не гарантировано: файл, уже превышающий лимит, но не тронутый текущей задачей, не будет назван. Гейт отвечает на «не вырос ли файл, который вы правите», а не на «нет ли в дереве файлов над лимитом».
Почему живём: это ratchet на изменении, а не аудит дерева: аудит потребовал бы объявить исключение для каждого исторического файла сразу, иначе он блокировал бы любую задачу за чужой долг. Полное дерево проверяется отдельной лентой.
Держит границу: run_filesize_gate(gate, files) принимает область задачи; tests/test_gates.py.
Круговой гейт проекции — opt-in и fail-open
Не гарантировано: расхождение дерева tausik/ с БД будет замечено в проекте, где БД отсутствует (гейт пропускает — на свежем клоне это правильный ответ), и внутренний сбой самого гейта не уронит коммит.
Почему живём: гейт, который блокировал бы проект без БД, заставлял бы завести БД, а не сходиться проекции. Сбой сторожа — не доказательство расхождения.
Держит границу: докстринг scripts/gate_state_roundtrip.py, tests/test_state_roundtrip_gate.py.
Маркер исторической цитаты проверяет ФОРМУ хеша, а не существование коммита
Не гарантировано: путь (удалён в <hex>) перестаёт считаться протухшей ссылкой, даже если такого коммита нет. Семь и более hex-символов в скобках сразу за путём — уже достаточное основание.
Почему живём: спросить у git — значит позволить сломанному git молча выключить весь детектор протухших ссылок; это дороже, чем поддельный маркер, который надо написать руками и который ничего не скрывает, кроме одной ссылки.
Держит границу: _REMOVED_CITATION в scripts/memory_cleanup.py, tests/test_repo_hygiene_ratchet.py.
Поиск модулей-сирот не видит имя, собранное выражением
Не гарантировано: модуль, к которому обращаются только как __import__(f"mod_{kind}"), будет назван сиротой. Строковый литерал (__import__("mod")) виден, вычисленное имя — нет.
Почему живём: вычисленное имя не называет ОДНОГО модуля, и догадка обменяла бы ложное срабатывание на ложный пропуск — детектор стал бы утверждать ссылку, которой не видел.
Держит границу: _dynamic_import_name в scripts/audit_orphan_files.py, tests/test_repo_hygiene_ratchet.py.
Проверка протухших ссылок требует, чтобы КАТАЛОГ существовал
Не гарантировано: ссылка на файл в удалённом целиком каталоге не будет названа протухшей.
Почему живём: проза полна слэшей, которые не пути (lru_cache/functools.cache, release/1.8). Требование существующего родителя убирает этот шум; без него список находок становится нечитаемым, и читатель перестаёт смотреть на настоящие.
Держит границу: _parent_dir_exists в scripts/memory_cleanup.py.
Архивация задач необратима и не уменьшает дерево
Не гарантировано: снять archived_at командой нельзя — такой команды нет; и файл проекции задачи остаётся в tausik/tasks/ после архивации, потому что экспортёр выбирает задачи без фильтра по этому полю (у памяти фильтр есть).
Почему живём: архивация задумана как «скрыть из task list», и в этой роли работает. Обе половины заведены задачами, и обратимость объявлена предусловием сокращения проекции.
Держит границу: docs/ru/task-archive-spec.md, оговорки в docs/ru/cli.md, tests/test_hygiene_cli.py.
Сервер MCP держит старый код до перезапуска IDE
Не гарантировано: правка в scripts/ немедленно доедет до инструментов MCP. До перезапуска хоста сервер может исполнять прежние модули.
Почему живём: перезагрузка модулей на живом сервере ломает состояние соединений дороже, чем стоит немедленность. Расхождение ОБЪЯВЛЯЕТСЯ: self_check.drift_detected поднимает флаг, и тогда ответам MCP в этой смене доверять нельзя — работает CLI, который перечитывает диск на каждый вызов.
Держит границу: tausik_self_check, раздел «MCP Health» в скилле /start.
/rewind не отменяет того, что агент сделал через shell
Не гарантировано: что /rewind в Claude Code вернёт файлы, изменённые агентом. Его чекпойнты отслеживают только правки собственными файловыми инструментами; всё, что записано через Bash, скрипт или другой процесс, в снимок не попадает и не откатывается.
Почему живём: это механизм хоста, а не наш, а агенты TAUSIK значительную часть работы делают через shell. Делать вид, что это не так, — значит оставить следующему агенту страховку, которой нет.
Держит границу: git. Перед рискованным шагом — коммит или stash; git diff покажет, чего откат не увидит.
Изменчивая часть файла правил стоит последней
Не гарантировано: что всё переданное агенту остаётся в кэше промпта. Хост кэширует самый длинный неизменный префикс, и изменившееся место обнуляет всё, что после него.
Почему живём: часть контекста обязана меняться — состояние сессии и хвост памяти. Она собрана в один блок в самом конце файла правил (<!-- DYNAMIC:START -->), после всех стабильных правил, поэтому её изменение стоит только её самой. Текст хуков на каждый промпт приходит после префикса разговора по той же причине.
Держит границу: tests/test_context_order.py падает, если после изменчивого блока стоит что-то стабильное — в порождённом файле правил или в CLAUDE.md этого репозитория.
Временные окна имеют СЕКУНДНУЮ гранулярность
Не гарантировано: событие, записанное в ту же секунду, в которую читается окно с верхней границей now, попадёт в выборку.
Почему живём: utcnow_iso() пишет секунды по всему проекту, и переход на миллисекунды затронул бы каждый timestamp в схеме и в проекции. Для открытого интервала верхняя граница просто не ставится — она бессмысленна.
Держит границу: запись памяти об окне событий, tests/test_med_findings_fix.py.
Проверки doctor — best-effort
Не гарантировано: падение отдельной проверки будет отличено от её отрицательного результата: исключение внутри проверки превращается в WARN с текстом ошибки, а не в FAIL.
Почему живём: doctor — обзор, а не гейт. Одна сломанная проверка не должна скрывать остальные девять.
Держит границу: scripts/project_cli_doctor.py (каждая проверка в своём try), tests/test_doctor_*.py.
Открытые дефекты
Руками здесь не перечисляются — и это решение, а не пропуск. Список дефектов, поддерживаемый вручную, отстаёт молча; ровно так документ, объявлявший себя картой направления, дошёл до утверждения про две версии назад. Открытые дефекты живут в БД задач, и оттуда их видно командой:
tausik task list --status planning # что заведено и ждёт
tausik roadmap # состав релиза со счётчикамиДефект, найденный внутри задачи, заводится отдельной задачей, а не правится походя — поэтому «ни одного открытого» здесь означало бы только то, что никто не смотрел.
Вне области
Чего TAUSIK не делает по замыслу, а не по недоделанности:
- Не правит падение гейта сам. Гейт называет проверку, причину и команду исправления; исправляет человек или агент. Гейт, который починил бы сам себя, учит не смотреть на причину.
- Не даёт агенту прямого доступа к БД. Только MCP и CLI. Прямой SQL обошёл бы проекцию, триггеры и квитанции — то есть всё, на чём держится воспроизводимость.
- Не заменяет ревью кода. Гейты проверяют дисциплину и границы, а не замысел. Разделение обязанностей L3 требует другой модели, чем у автора.
- Не обслуживает несколько проектов из одного демона. Сервер MCP привязан к проекту при запуске; общесистемный режим — предмет отдельной большой работы, а не пробел.