Переформулировано. Исходно issue просил --scope memory-bank/ для pull. Это была неверная постановка: она исходила из того, что репозиторий-источник шаблона держит у себя копию payload. Он не должен её держать — и CLI сам это утверждает (см. ниже). Настоящий запрос другой.
Топология
Репозиторий dapi/memory-bank — источник шаблона и одновременно его потребитель: template/memory-bank/ — payload, memory-bank/ — project-local Memory Bank этого проекта.
Копии payload там больше нет. Generic-документы представлены симлинками в payload по соответствующему пути:
memory-bank/flows/routing.md -> ../../template/memory-bank/flows/routing.md
memory-bank/dna/principles.md -> ../../template/memory-bank/dna/principles.md
Реальными файлами остаются только те документы, которыми владеет или которые переопределяет проект. Это не обходной приём, а осознанная модель: инстанс равен payload по построению, синхронизировать нечего, дрейфа не существует.
Что делает CLI сегодня
1. doctor считает такой симлинк дефектом, если файл числится в lock:
error manifest.managed_unreadable memory-bank/flows/routing.md
Managed file cannot be inspected: unsafe symlink in path "memory-bank/flows/routing.md"
remediation: Restore the file from the pinned template with memory-bank-cli pull.
При полной проекции это 110 ошибок — по одной на документ.
2. pull и init останавливаются на unsafe path ещё до чтения, если симлинк встречается в любом компоненте пути назначения.
3. lint при этом работает корректно — читает сквозь файловый симлинк, документ попадает в область, навигация и индексы проверяются как обычно.
То есть инструменты расходятся между собой: для lint проекция — нормальный документ, для doctor — неисправность.
Почему строгое правило верно в общем случае и промахивается здесь
Запрет нужен, чтобы запись не ушла за пределы репозитория по подменённой ссылке. Это правильная защита для записи по destination path.
Но у проекции цель разрешается внутрь того же репозитория, ровно в тот payload-файл, которым CLI и так управляет. Ни выхода за корень, ни traversal, ни TOCTOU-подмены: цель — соседний путь в том же коммите.
Показательно, что CLI уже знает про эту топологию. Стоит убрать lock, и он сам формулирует правило:
$ memory-bank-cli doctor --profile template
info template.source_repository Template source profile detected;
an installed-template lock is not expected.
remediation: Create locks only in downstream repositories through memory-bank-cli init.
Result: 0 error(s), 0 warning(s), 1 info
Если репозиторию-источнику не положен lock, то не положена и копия. Проекция — прямое следствие этого же правила, просто CLI пока о ней не знает.
Предлагаемое поведение
- Симлинк под
memory-bank/, чья цель после разрешения остаётся внутри корня репозитория и указывает на template/memory-bank/<тот же относительный путь>, считать намеренной проекцией, а не managed_unreadable. В профиле template это нормальное состояние, максимум — info.
- Продолжать отклонять симлинки, которые разрешаются за пределы корня или указывают не на соответствующий payload-файл: именно они и опасны.
- Для
pull и init как минимум различать эти два случая в тексте ошибки. Сейчас сообщение одинаковое, и оператор не понимает, наткнулся он на защиту от traversal или на осознанную конструкцию своего же репозитория.
Побочная находка: lint и симлинки на директории
lint читает сквозь симлинк на файл, но не спускается в симлинк на директорию. Замена memory-bank/flows одним симлинком на template/memory-bank/flows уронила область со 120 файлов до 68, и все ссылки внутрь flows/ были объявлены битыми — без единого предупреждения о том, что каталог просто не обошли.
Из-за этого проекцию пришлось делать пофайловой (110 симлинков вместо 8 каталожных). Само по себе терпимо, но разное отношение к файловым и каталожным симлинкам стоит либо выровнять, либо назвать явно в диагностике.
Топология
Репозиторий
dapi/memory-bank— источник шаблона и одновременно его потребитель:template/memory-bank/— payload,memory-bank/— project-local Memory Bank этого проекта.Копии payload там больше нет. Generic-документы представлены симлинками в payload по соответствующему пути:
Реальными файлами остаются только те документы, которыми владеет или которые переопределяет проект. Это не обходной приём, а осознанная модель: инстанс равен payload по построению, синхронизировать нечего, дрейфа не существует.
Что делает CLI сегодня
1.
doctorсчитает такой симлинк дефектом, если файл числится в lock:При полной проекции это 110 ошибок — по одной на документ.
2.
pullиinitостанавливаются на unsafe path ещё до чтения, если симлинк встречается в любом компоненте пути назначения.3.
lintпри этом работает корректно — читает сквозь файловый симлинк, документ попадает в область, навигация и индексы проверяются как обычно.То есть инструменты расходятся между собой: для
lintпроекция — нормальный документ, дляdoctor— неисправность.Почему строгое правило верно в общем случае и промахивается здесь
Запрет нужен, чтобы запись не ушла за пределы репозитория по подменённой ссылке. Это правильная защита для записи по destination path.
Но у проекции цель разрешается внутрь того же репозитория, ровно в тот payload-файл, которым CLI и так управляет. Ни выхода за корень, ни traversal, ни TOCTOU-подмены: цель — соседний путь в том же коммите.
Показательно, что CLI уже знает про эту топологию. Стоит убрать lock, и он сам формулирует правило:
Если репозиторию-источнику не положен lock, то не положена и копия. Проекция — прямое следствие этого же правила, просто CLI пока о ней не знает.
Предлагаемое поведение
memory-bank/, чья цель после разрешения остаётся внутри корня репозитория и указывает наtemplate/memory-bank/<тот же относительный путь>, считать намеренной проекцией, а неmanaged_unreadable. В профиле template это нормальное состояние, максимум —info.pullиinitкак минимум различать эти два случая в тексте ошибки. Сейчас сообщение одинаковое, и оператор не понимает, наткнулся он на защиту от traversal или на осознанную конструкцию своего же репозитория.Побочная находка:
lintи симлинки на директорииlintчитает сквозь симлинк на файл, но не спускается в симлинк на директорию. Заменаmemory-bank/flowsодним симлинком наtemplate/memory-bank/flowsуронила область со 120 файлов до 68, и все ссылки внутрьflows/были объявлены битыми — без единого предупреждения о том, что каталог просто не обошли.Из-за этого проекцию пришлось делать пофайловой (110 симлинков вместо 8 каталожных). Само по себе терпимо, но разное отношение к файловым и каталожным симлинкам стоит либо выровнять, либо назвать явно в диагностике.