@deksden-com/mb-lint
v0.3.1
Published
Deterministic linter for Memory Bank projects.
Readme
mb-lint
mb-lint - детерминированный линтер Банка памяти (Memory Bank).
Он должен проверять то, что можно проверить формально: структуру, ссылки, frontmatter, идентификаторы, достижимость документов, качество DEF-* и связи из кода в документацию. Он не должен заменять смысловой аудит, архитектурное ревью или решение пользователя.
Зачем нужен проект
Банк памяти помогает людям и ИИ-агентам работать с проектом через устойчивые документы: спецификации, ADR, планы, сценарии, пользовательские инструкции, операционные правила и доказательства. Но со временем такая система может расползаться:
- появляются битые ссылки;
- документы теряют достижимость из индексов;
- один и тот же смысл дублируется в разных местах;
DEF-*остаются без владельца или следующего шага;- кодовые комментарии ссылаются на несуществующие фичи, сценарии или ADR;
- корневая структура перестаёт соответствовать канону.
mb-lint должен закрывать механическую часть этой проблемы. Всё, что требует понимания смысла, остаётся задачей mb-audit и обычного ревью.
Запуск
Опубликованный пакет запускается так:
npx @deksden-com/mb-lint@latestЛокально из репозитория:
npm install
npm run build
node ./dist/cli.js --root . --format text
node ./dist/cli.js --root . --format jsonЧтобы временно сделать локальную сборку глобальной командой без установки из npm:
npm run build
npm link
mb-lint --helpnpm link создаёт глобальную ссылку на текущую рабочую копию. После проверки её можно снять командой npm unlink -g @deksden-com/mb-lint.
Поддерживаемые режимы v0.1:
npx @deksden-com/mb-lint@latest --root .
npx @deksden-com/mb-lint@latest --memory-bank .memory-bank
npx @deksden-com/mb-lint@latest --format json
npx @deksden-com/mb-lint@latest rulesВ текущем CLI есть --root, --memory-bank, --format text|json, --help, --version and rules. Warning-as-error флаг будет спроектирован позже.
Конфигурация
Если проект содержит намеренно битые примеры, fixtures или ссылки, которые не должны проверяться, добавь .mb-lint.json в корень проекта:
{
"ignorePaths": ["test/fixtures/**"],
"ignoreFindings": [
{
"ruleId": "links/markdown-target-exists",
"file": ".memory-bank/example.md",
"target": "missing-example.md",
"reason": "Intentional example link."
}
]
}ignorePaths исключает файлы целиком. ignoreFindings исключает конкретные findings по ruleId, file и target. Игнор должен быть намеренным: если ссылка должна работать как активная навигация, её нужно чинить, а не скрывать.
Git-aware поведение включено по умолчанию, если проект является Git-репозиторием:
{
"git": {
"respectIgnore": true
}
}Когда git.respectIgnore не равен false, mb-lint исключает из входного набора файлы, которые одновременно ignored by Git и untracked. Обычные untracked файлы не исключаются: новые документы до git add всё ещё должны линтиться.
Ignored рабочие каталоги вроде .tasks/ не сканируются целиком. Если активный документ ссылается на ignored+untracked файл, mb-lint проверяет только конкретный resolved target этой ссылки и выдаёт отдельную ошибку links/target-ignored-untracked, потому что такая ссылка ведёт к материалу, который не попадёт в репозиторий.
Что проверяет mb-lint сейчас
Текущая реализация проверяет только детерминированные свойства:
- есть ли
.memory-bank/или другой явно указанный путь; - есть ли корневые
index.mdиstructure.md; - корректны ли Markdown-ссылки;
- существуют ли файлы, указанные в поддерживаемых frontmatter relation fields;
- заполнены ли обязательные поля frontmatter;
- совпадает ли frontmatter
fileс project-root-relative или MemoryBank-root-relative путём документа; statusиспользуетACTIVE,DRAFTилиDEPRECATED;dateимеет форматYYYY-MM-DD;versionимеет форматmajor.minor.patch;- path-like frontmatter поля не используют абсолютные локальные пути;
- type-aware enum/id checks для явно распознанных protocols, protocol sets, ADRs, scenarios and evidence docs;
- JS/TS doc tags ссылаются на существующие документы Memory Bank;
- активные Markdown/frontmatter/code ссылки не указывают на git-ignored untracked файлы.
Поддерживаемые frontmatter target fields:
parent, children, related_files,
related_epics, related_features, related_specs, related_adrs, related_scenarios, related_protocols,
evidence_files, implementation_files, test_files,
protocol_set, source_user_input,
adr, spec, feature, scenarioКоманда ниже выводит список фактически реализованных правил и ссылки на документы канона:
mb-lint rulesПроверки DEF-*:
- у
DEF-*есть причина; - указан владелец;
- указан следующий gate;
- есть контекст продолжения;
- понятно, зависит ли блокер от пользователя;
- указано, что блокируется и что не блокируется;
- статус согласован с содержанием;
- закрытый
DEF-*содержит след закрытия.
Проверки связей кода с Банком памяти:
- теги
@doc,@docs,@feature,@scenario,@adr,@spec,@evidence,@epic,@protocolссылаются на существующие документы; - ссылки в JSDoc/TSDoc/docstrings ведут в существующие файлы, когда они оформлены через поддерживаемые doc tags.
Что пока остаётся кандидатом
Эти проверки описывают желаемое развитие, но не должны считаться реализованными без отдельного rule id:
- соответствует ли карта папок канонической структуре проекта;
- достижимы ли активные документы из индексов;
- нет ли активных документов, которые лежат только как сироты;
- нет ли одинаковых
id; - согласован ли статус документа с его местом:
ACTIVE,DRAFT,DEPRECATED,ARCHIVED; - не лежит ли архивный документ в активном разделе без пометки;
- не используют ли сценарии, протоколы и матрицы проверки
.tasks/...как evidence после закрытия работы; - нет ли trailing spaces и базовой Markdown-грязи;
- публичные границы, которые требуют документации по проектным правилам, имеют ссылку на документ;
- кодовые контракты интерфейса ссылаются на существующие экранные или сценарные спецификации.
Что mb-lint не должен делать
mb-lint не должен решать смысловые вопросы:
- хороша ли архитектура;
- правильно ли выбран стек;
- достаточно ли хорошо описана фича;
- актуальна ли спецификация по смыслу;
- нужно ли включать найденную практику в канон;
- какой вариант ответа выбрать за пользователя.
Если проверка требует рассуждения, это не lint-правило, а тема для mb-audit, mb-distill, ADR или обсуждения.
Источники для будущего mb-init
Этот README должен быть одним из источников при запуске mb-init на проекте mb-lint.
mb-init должен читать:
- README;
- будущий
package.json; - исходный код CLI;
- тесты;
- конфигурации сборки, линтера и форматтера;
- комментарии в коде, включая JSDoc/TSDoc;
- examples и fixtures;
- CI/CD;
.tasks/, если они появятся.
Если кодовые комментарии объясняют правило, контракт или ограничение, mb-init должен учитывать их как источник. Если комментарий противоречит коду, это не становится истиной автоматически: агент должен вынести противоречие в отчёт и при необходимости задать вопрос пользователю.
Предполагаемая архитектура
Первая версия реализована как CLI на TypeScript.
Основные части:
- CLI-вход: разбирает аргументы, находит корень проекта и путь Банка памяти;
- загрузчик правил: собирает кодовые модули правил;
- сканер Markdown: строит карту документов, ссылок и frontmatter;
- сканер кода: извлекает JSDoc/TSDoc/docstrings и проверяет ссылки на Банк памяти;
- движок правил: применяет детерминированные проверки;
- репортёр: выводит текстовый отчёт и JSON;
- режим exit codes: возвращает ненулевой код при ошибках нужной серьёзности.
Стек v0.1:
- TypeScript;
gray-matterдля frontmatter;- Vitest для тестов;
- регулярные выражения для детерминированного извлечения Markdown-ссылок и JS/TS doc tags.
Tree-sitter можно рассмотреть позже, когда появится многоязычный анализ Python, Go, PHP или других стеков.
Проверки разработки
npm run typecheck
npm run build
npm test
npm run lint
node ./dist/cli.js --root test/fixtures/valid-memory-bank --format json
node ./dist/cli.js --root test/fixtures/invalid-memory-bank --format json
node ./dist/cli.js --root test/fixtures/code-doc-tags --format json
node ./dist/cli.js rulesДля валидного fixture ожидается exit code 0; для fixtures с ошибками ожидается exit code 1.
Правила канона описываются кодом. Каждое правило должно быть отдельным модулем с метаданными, стабильным ruleId, детерминированной проверкой и структурированными findings. Архитектурный ориентир - модульный подход Biome/ESLint. В первой версии это внутренняя модульность, а не публичный plugin API.
Frontmatter rules are intentionally conservative. They validate explicit machine-readable contracts from .memory-bank/mbb/frontmatter-standards.md and related MBB docs; they do not infer whether optional links such as feature/spec/ADR/scenario should exist for a given document.
Уровни серьёзности
Ожидаемые уровни:
error- ошибка ломает навигацию, трассировку или обязательный контракт;warning- проблема не ломает работу, но ухудшает качество Банка памяти;info- полезное замечание;suggestion- кандидат на улучшение.
Для CLI важно различать:
- ошибки, которые должны ломать CI по умолчанию;
- предупреждения, которые видны в отчёте, но не блокируют работу;
- рекомендации, которые можно отложить.
По умолчанию CI ломают только error. Warning-as-error режим можно добавить отдельным флагом позже.
Машиночитаемый отчёт
JSON-отчёт должен быть пригоден для агентов и CI:
{
"tool": "mb-lint",
"version": "0.0.0",
"root": ".",
"memoryBank": ".memory-bank",
"summary": {
"errors": 0,
"warnings": 0,
"info": 0
},
"findings": [
{
"ruleId": "links/no-broken-markdown-link",
"severity": "error",
"file": ".memory-bank/index.md",
"message": "Link target does not exist",
"target": ".memory-bank/spec/system/missing.md"
}
]
}Решения для первой версии
- Пакет:
@deksden-com/mb-lint. - Первая версия только сообщает ошибки и не выполняет автоисправления.
- CI по умолчанию ломают только
error. - Локальный конфиг в первой версии не нужен.
- Канонические теги кода:
@doc,@docs,@feature,@scenario,@adr,@spec,@evidence,@epic,@protocol. - Первая версия проверяет Markdown и JS/TS.
- Стартовый стек: TypeScript CLI.
- Правила канона описываются кодовыми модулями правил.
- Первая версия делает full scan, без режима проверки только изменённых файлов в pull request.
Оставшиеся открытые вопросы
- Как описывать проектные исключения после появления локального конфига: в конфиге, в frontmatter или отдельном ignore-файле?
- Как хранить и версионировать rule modules, если канон
dd-memorybankменяется? - Как оформлять rule profile для проверки локальных рабочих папок, если проект сознательно коммитит часть
.tasks/? - Как назвать будущий warning-as-error режим:
--strict,--error-on-warnings,--max-warningsили иначе?
Связь с dd-memorybank
dd-memorybank описывает канон Банка памяти и промпты работы с ним.
mb-lint должен быть отдельным инструментом, чтобы:
- его можно было запускать в любом проекте;
- он не смешивал код линтера с каноном;
- его можно было подключить в CI;
- агенты могли использовать его как источник механических фактов перед
mb-auditилиmb-fix.
Идеальный поток:
mb-init создаёт Банк памяти
-> mb-lint проверяет механическую целостность
-> mb-audit проверяет смысловые аспекты
-> mb-fix исправляет выбранные проблемы