Skip to main content
Glama
Parker-Fawcett

rebuild-dossier

rebuild-dossier

DOI

MCP-сервер, который восстанавливает из существующего приложения надёжную спецификацию пересборки — зафиксированный CLAUDE.md, конфиг .claude/ и прошедший мутационное тестирование набор тестов, — чтобы любой агент кодирования мог чисто пересобрать приложение по этой спецификации, а не гадать.

Он не пересобирает приложение. Он создаёт спецификацию, контракты и тесты, которые агент кодирования потребляет для этого отдельно. Эта граница намеренная — см. Зачем ниже.

Статус: v0. Основной цикл работает и был проверен end-to-end на одном реальном, запутанном репозитории, включая две независимые передачи свежему агенту на двух уровнях моделей. Прочитайте docs/v0-findings.md для честного результата, включая то, что сломалось.

Зачем

Предыдущее исследование (AgentModernize, arXiv:2605.17535) показало, что конвейер пересборки достигает 0% поведенческой эквивалентности без проверяемого цикла обратной связи и только 9–19% с грубым циклом. Ставка этого инструмента: фиксация интерфейсных контрактов до запуска тестов, плюс строгий цикл повторных попыток по одному тесту за раз вместо пакетной регенерации, даёт заметно лучший результат.

Самая рискованная часть любого такого конвейера — молчаливое подтверждение бага как намеренного поведения: четыре источника доказательств могут тихо согласиться на одну и ту же ошибку, и никто ни разу не объяснил почему. Поэтому единственное незыблемое правило в этом инструменте: автоматическое разрешение неоднозначности требует как согласия сигналов, так и утвердительного сигнала о том, что кто-то действительно принял решение (явный комментарий, TODO, признающий баг, или прямой ответ человека). Молчаливое согласие — простое совпадение кода и наблюдаемого поведения, без единого объяснения, — всегда становится вопросом, а не автоматическим разрешением, независимо от того, насколько высока кажущаяся уверенность.

Related MCP server: reforge-mcp

Как это работает

Шесть MCP-инструментов, запускаемых из обычной сессии Claude Code (или любого MCP-совместимого клиента):

Инструмент

Что делает

ingest_repo(path)

Только статический анализ, без вызова LLM: маршруты, package.json, конфиг сборки (через AST, никогда не выполняется), существующие тесты и детекторы структурных запахов (например, проверка учётных данных только на клиенте без серверной верификации), которые выявляют реальную неоднозначность, даже если никто никогда не комментировал её.

crawl_site(url)

Безголовый обход Playwright доступных маршрутов, с уведомлениями о прогрессе, чтобы длинные обходы не убивались как неотвечающие.

flag_known_bug(description)

Свободный текст, сохраняется дословно. Всегда переопределяет авторазрешение для всего, что ему соответствует, — самый дешёвый и авторитетный сигнал в системе.

get_case_queue() / resolve_case(id, decision)

Очередь неоднозначностей. Отображает открытые вопросы через MCP-elicitation, если клиент это поддерживает; resolve_case всегда доступен как скриптовый запасной вариант.

generate_spec()

Можно вызывать только когда очередь случаев пуста. Записывает CLAUDE.md, .claude/rules/, .claude/settings.json (хуки, которые механически обеспечивают дисциплину — см. ниже), spec/contracts/*.md, tests/visible/ + tests/held-out/ и kickoff-prompt.txt в чистую соседнюю директорию <repo>-rebuild/ — никогда в исходный репозиторий. Перед финализацией тестов выполняет настоящую мутационную проверку: намеренно ломает исходный код и подтверждает, что каждый сгенерированный тест действительно его ловит, понижая те, которые не ловят.

Правила, которые обеспечиваются механически, а не просто записаны

Сравнительный прогон на двух уровнях моделей показал, что более слабая модель с удовольствием прочитает CLAUDE.md, поймёт «создавай только то, что сейчас падает, не регенерируй пакетно» — и затем тихо нарушит это, потому что ничто не проверяло её. Два правила в этом инструменте теперь обеспечиваются реальными хуками, а не прозой, именно по этой причине:

  • spec/ заблокирован. Хук PreToolUse блокирует любые правки в spec/.

  • Контракты без тестов не строятся раньше времени. generate_spec записывает spec/untested-contracts.json (каждый маршрут/контракт без покрывающего теста), а второй хук PreToolUse блокирует запись в любой элемент этого списка — та же форма обеспечения, что и блокировка правок spec/, закрывающая пробел, который раньше был только рекомендательным.

Хук PostToolUse запускает видимый набор тестов после каждой правки.

Быстрый старт

git clone https://github.com/businessfawcett-cloud/rebuild-dossier.git
cd rebuild-dossier
npm install
npx playwright install chromium   # needed for crawl_site

Добавьте его как MCP-сервер в Claude Code (или любой MCP-совместимый клиент), затем в сессии:

ingest_repo({ path: "/path/to/some-app" })
get_case_queue({ repoPath: "/path/to/some-app", interactive: true })
# ...resolve whatever the queue surfaces...
generate_spec({ repoPath: "/path/to/some-app" })

Это создаст чистую соседнюю директорию some-app-rebuild/. Перейдите в неё, запустите новую сессию Claude Code (ничего другого не должно быть в области видимости) и вставьте содержимое её kickoff-prompt.txt.

Руководство по эксплуатации

Полный жизненный цикл по порядку — фактическое поведение каждого шага, а не только сигнатура вызова.

1. Ингест репозитория

ingest_repo({ path: "/absolute/path/to/some-app" })

Только статический анализ — без вызова LLM, ничего не выполняется. Разбирает package.json, файлы маршрутов (Express и Next.js App Router на сегодня — см. область применения), конфиг сборки (Tailwind/Vite/Next, через AST, никогда не выполняется), существующие тесты и сканирует сигналы комментариев/TODO плюс структурные запахи (например, жёстко закодированная проверка учётных данных на клиенте без серверной верификации — то, о чём никто никогда не комментирует, и именно поэтому нужен собственный детектор, а не опора на существование комментариев). Всё попадает в <repo>/.dossier/ — собственное временное состояние этого инструмента, внутри исходного репозитория, никогда не публикуется и не загружается никуда. Вы получите сводку:

{
  "routes": 8,
  "existingTests": 0,
  "signals": 3,
  "buildConfig": ["tailwind", "next"],
  "openCases": 3,
  "savedTo": "/absolute/path/to/some-app/.dossier/evidence.json"
}

openCases здесь уже отражает согласование — сигналы комментариев/TODO и структурные запахи, которые не авторазрешились, автоматически становятся записями очереди случаев.

Если routes возвращает 0, проверьте поле monorepoHint, прежде чем предполагать, что в приложении нет маршрутов — ingest_repo нужно указывать на фактическую директорию приложения, а не на корневой обёртку монорепозитория (package.json с apps/*/packages/* рядом, что часто встречается в макетах Turborepo/Nx/workspace, включая те, которые никогда не объявляют поле workspaces). Подсказка перечисляет реальные кандидаты-директории, найденные в apps//packages/, чтобы вам не пришлось искать настоящее приложение самостоятельно — повторно запустите ingest_repo, указав на одну из них.

Если ваш клиент поддерживает MCP-elicitation, вы можете пропустить ручной повторный запуск: передайте interactive: true, и когда обнаружен корень монорепозитория с кандидатами, ingest_repo спрашивает, какая из них является настоящим приложением, и ингестит его напрямую — он никогда не угадывает молча, так же как интерактивный режим get_case_queue всегда спрашивает, а не разрешает что-либо без вас. Отказ, неподдерживаемый клиент или ответ, не являющийся одним из реальных кандидатов, — всё это возвращается к простой подсказке выше, без изменений.

2. (Необязательно) Обход живого сайта

crawl_site({ url: "http://localhost:3000", repoPath: "/absolute/path/to/some-app" })

Полезно только если приложение где-то реально запущено. Безголовый обход Playwright доступных маршрутов, с периодическими уведомлениями о прогрессе — длинные обходы автоматически уходят в фоновый режим в большинстве MCP-клиентов, и молчаливый многоминутный вызов рискует быть убитым как неотвечающий без них.

3. (Необязательно, но сделайте это перед шагом 4) Отметьте всё, что вы уже знаете как сломанное

flag_known_bug({
  repoPath: "/absolute/path/to/some-app",
  description: "The login gate secret check runs entirely client-side and is bypassable"
})

Самый дешёвый и авторитетный сигнал во всей системе — прямое человеческое утверждение всегда перевешивает выводы. Он переопределяет авторазрешение для всего, что ему соответствует, даже если все остальные сигналы тихо соглашаются, что поведение выглядит намеренным. Делайте это до разрешения очереди, поскольку это меняет то, что там появляется (и может породить случай полностью самостоятельно, без каких-либо других доказательств — см. docs/v0-findings.md для объяснения, почему это важно).

Сопоставление — это простое пересечение токенов с путём файла и текстом утверждения каждого открытого случая, не нечёткое или семантическое — поэтому одно описание бага может сопоставиться (и авторазрешить) больше открытых случаев, чем вы намеревались, если в вашей кодовой базе есть несколько компонентов с похожими именами. В проверенном примере один баг о «входном гейте» сопоставился и закрыл все три почти дублирующихся гейт-компонента Madeline одним вызовом, до того как любой из них был рассмотрен индивидуально. resolve_case перезаписывает решение случая независимо от его текущего статуса, так что если это не то, что вы имели в виду, вызовите его напрямую для тех, которые он захватил слишком широко — не предполагайте, что каждый затронутый случай был тем же решением.

4. Разрешите очередь случаев

get_case_queue({ repoPath: "/absolute/path/to/some-app", interactive: true })

interactive: true проходит по каждому открытому случаю через MCP-elicitation — реальный интерактивный запрос в вашем клиенте, показывающий доказательства бок о бок, если ваш клиент это поддерживает. Если нет (или вы скриптуете это), разрешайте случаи по одному:

resolve_case({ repoPath: "/absolute/path/to/some-app", id: "case:...", decision: "intentional", note: "..." })

У этого шага нет ярлыка. generate_spec отказывается запускаться, пока любой случай ещё открыт, по замыслу — не существует частичной или незавершённой спецификации, которую можно передать агенту пересборки с оговорками; фазы 1–2 буквально создают spec/ в первую очередь.

5. Сгенерируйте спецификацию

generate_spec({ repoPath: "/absolute/path/to/some-app" })

Вызывается только после того, как очередь пуста. Записывает CLAUDE.md, .claude/ (правила, хуки, субагент spec-auditor и навык verify-against-spec — всё это выводится из реальных контрактов и тестов этого проекта, а не из шаблонов), spec/ (контракты, зафиксированные решения, test-dependencies.json, untested-contracts.json) и tests/ в чистую соседнюю директорию some-app-rebuild/ — никогда в исходный репозиторий. Ещё два артефакта .claude/ создаются только тогда, когда они действительно нужны: субагент test-verifier — только если есть отложенные тесты для защиты; workflow parallel-test-fix — только если сгенерированные тесты разбиваются на два или более независимых кластера (по общим файлам маршрутов), которые стоит исправлять параллельно. Небольшое приложение с парой тестов, покрывающих одни и те же маршруты — как в проверенном примере выше — не получает ни того, ни другого; это не баг, это генератор отказывается давать агенту по пересборке инструменты, с которыми ему нечего делать. Этот шаг также выполняет настоящую мутационную проверку: он намеренно ломает исходный код (инвертирует сравнение, убирает проверку на null, сдвигает границу цикла на единицу) в черновой копии и подтверждает, что каждый сгенерированный тест действительно ловит это — всё, что не ловит, перемещается в tests/weak/ вместо того, чтобы быть опубликованным как заслуживающий доверия. Вы получите:

{
  "outputDir": "/absolute/path/to/some-app-rebuild",
  "mutationsChecked": 8,
  "weakTests": [],
  "unrunnableTests": []
}

И weakTests, и unrunnableTests попадают в одну и ту же директорию tests/weak/ вместо tests/visible/, но по разным причинам, которые стоит различать: слабый тест выполнялся нормально и просто никогда не ловил ничего, что ломала мутация; невыполнимый тест никогда не проходил даже против исходного, немутированного кода (сломанный импорт, отсутствующая переменная окружения, инфраструктура, которой нет в голом репозитории) — до появления этого различия невыполнимый тест выглядел неотличимым от 100% эффективного, поскольку он «падает» одинаково, мутирован ли тестируемый код или нет. Ни то, ни другое не является ошибкой — это инструмент честно сообщает вам, что конкретный тест не заслужил своего места в tests/visible/, и почему.

Если все сгенерированные тесты попадают в tests/weak/ с mutationsChecked: 0, проверьте поле warning, прежде чем предполагать, что что-то структурно не так — гораздо более распространённая причина в том, что в целевом репозитории не выполнялся npm install, поэтому в черновой копии для мутационной проверки нет ни одной из реальных зависимостей цели (next, @prisma/client, что бы там ни требовалось приложению), и каждый сгенерированный тест не может даже импортировать их. generate_spec проверяет это напрямую и сообщает об этом, а не оставляет вас разбираться с запутанным результатом, где всё невыполнимо.

Необязательно: классификация содержимого страниц с помощью зрения

Для цели на Next.js маршруты страниц получают настоящие тесты, захваченные Playwright (скриншот плюс проверки DOM-текста), наряду с описанными выше тестами API-маршрутов. Определяется ли фрагмент захваченного текста как точное совпадение (static) или как свободная проверка формы (dynamic), по умолчанию решает небольшой regex-классификатор — в большинстве случаев надёжный, но подтверждено, что он может ошибаться в обе стороны на реальном приложении (жёстко заданная легенда выпадающего списка прочитана как живые данные; живой счётчик базы данных с запятыми прочитан как фиксированный).

Установка обоих GROQ_API_KEY и REBUILD_DOSSIER_ENABLE_VISION_CLASSIFICATION=1 перед вызовом generate_spec отправляет скриншот каждой захваченной страницы и (с удалёнными секретами) исходный код в зрительную модель Groq, которая может видеть, откуда на самом деле берётся значение — литеральный массив в исходнике против вызова fetch/useState — а не только догадываться по виду отрендеренной строки. Обе переменные требуются вместе намеренно: случайный GROQ_API_KEY, оставшийся от какого-то несвязанного инструмента, никогда не должен молча начать отправлять код этого целевого репозитория третьей стороне. Ни одна из переменных не установлена (по умолчанию) — значит, нулевое изменение поведения и нулевые сетевые вызовы сверх того, что уже делает generate_spec.

Это реальная дополнительная стоимость, а не бесплатно: один вызов API Groq на каждую захваченную страницу плюс намеренная задержка ~20 секунд между страницами (у бесплатного тарифа Groq жёсткий посекундный лимит токенов, и отправка запросов подряд быстро его исчерпывает) — в собственном ответе generate_spec указывается точное добавленное время для этого запуска. Страница, которую нельзя классифицировать таким образом по любой причине (лимит скорости, сетевая проблема, недопустимый ответ), возвращается к regex-классификатору только для этой страницы, о чём сообщается в pageVisionFallbacks — никогда не молчаливый пропуск или неудачный запуск. Бесплатного тарифа Groq (без кредитной карты, на console.groq.com) достаточно, чтобы попробовать это.

6. Передача

cd /absolute/path/to/some-app-rebuild
claude   # or oh-my-pi, opencode — any coding agent, a genuinely fresh session

Вставьте содержимое kickoff-prompt.txt дословно. В контексте этого сеанса больше ничего не должно быть — директория намеренно полностью самодостаточна (см. Как это работает), так что агенту по пересборке больше нечего читать, к чему дрейфовать или что редактировать на месте вместо чистой сборки. Прочтите docs/v0-findings.md, чтобы узнать, что на самом деле происходит, когда вы делаете это с реальным приложением, включая точное место, где он застрял.

Подключение из других инструментов (oh-my-pi, opencode и т. д.)

Два способа запуска, оба полностью локальные — нет размещённого/общего экземпляра, и он не требуется:

stdio (по умолчанию) — каждый инструмент запускает свою собственную копию сервера как локальный подпроцесс. Это стандартный способ, которым каждый MCP-клиент (Claude Code, oh-my-pi, opencode) добавляет локальный MCP-сервер — укажите на npx tsx src/index.ts (или собранный node dist/index.js) из директории этого репозитория. Никакой дополнительной настройки, никакой аутентификации, ничего из этого раздела не применяется.

HTTP (необязательно) — один постоянный сервер на localhost, к которому подключаются несколько инструментов/сеансов, вместо того чтобы каждый запускал свой собственный. Полезно, если вы хотите, чтобы oh-my-pi и opencode (или несколько сеансов Claude Code) использовали один работающий экземпляр. Всё ещё полностью локально — MCP_ALLOWED_HOSTS должен включать только имя хоста, к которому вы действительно будете подключаться (localhost), а не реальный домен, если только вы намеренно не решите открыть доступ за пределы своей машины.

npm run build
PORT=8080 \
MCP_AUTH_TOKEN=$(openssl rand -hex 32) \
MCP_ALLOWED_HOSTS=localhost,127.0.0.1 \
REBUILD_DOSSIER_ALLOWED_PATHS=/absolute/path/to/your/projects \
npm run start:http:prod

Все три переменные окружения обязательны — сервер отказывается запускаться без них намеренно: MCP_AUTH_TOKEN ограничивает каждый запрос /mcp (bearer-аутентификация), MCP_ALLOWED_HOSTS защищает от DNS-rebinding, а REBUILD_DOSSIER_ALLOWED_PATHS (абсолютные директории через запятую) — единственные пути, к которым ingest_repo/generate_spec/и т. д. имеют право обращаться — установите его в родительскую директорию, содержащую репозитории, которые вы действительно хотите пересобрать.

oh-my-pi (.omp/mcp.json или ~/.omp/agent/mcp.json):

{
  "mcpServers": {
    "rebuild-dossier": {
      "type": "http",
      "url": "http://localhost:8080/mcp",
      "headers": { "Authorization": "Bearer ${REBUILD_DOSSIER_TOKEN}" }
    }
  }
}

opencode (opencode.json):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "rebuild-dossier": {
      "type": "remote",
      "url": "http://localhost:8080/mcp",
      "enabled": true,
      "oauth": false,
      "headers": { "Authorization": "Bearer {env:REBUILD_DOSSIER_TOKEN}" }
    }
  }
}

oauth: false отключает автоматическое обнаружение OAuth в opencode при получении 401 — этот сервер поддерживает только статический bearer-токен, указанный выше, а не настоящий поток OAuth. Установите указанную переменную окружения (REBUILD_DOSSIER_TOKEN в обоих примерах) в то же значение, что и MCP_AUTH_TOKEN выше.

Разработка

npm test        # full suite
npm run typecheck

Небольшие функции с одной целью; TDD повсюду (тесты пишутся до реализации, которую они покрывают, включая саму логику сверки — это инструмент, который генерирует тесты, поэтому его собственная корректность важна не меньше любой функции).

Текущий объём и что намеренно ещё не построено

v0 ограничен доказательством основного цикла, а не полнотой функций. Намеренно отложено и отслеживается как реальный бэклог, а не молча пропущено:

  • Сверка по неоднозначности формы API (правило валидации, форма ответа об ошибке) всё ещё по-настоящему не протестирована — единственное реальное приложение с другой формой, проверенное на данный момент (catchandtrade), случайно имело нулевые сигналы комментариев/TODO для сверки, так что этот конкретный вопрос пока не имеет ответа ни в ту, ни в другую сторону. См. docs/v0-findings.md.

  • Приём видео/записи экрана и проверка помеченных окон видео-LLM.

  • Оригинальный CLAUDE.md / авто-память как источник доказательств.

  • Живой захват Chrome MCP для потоков с аутентификацией/несколькими аккаунтами, недоступных headless-краулеру.

  • Извлечение манифеста ресурсов (двоичные файлы, скопированные байт-в-байт + хэш-манифест, зафиксированный уровень контракта) — реальный дизайн существует, но ещё не реализован.

  • Мутатор, который полностью отключает обработчик (текущие три — инвертирование сравнения, удаление проверки на null, сдвиг на единицу — не могут создать мутанта «эта ветка никогда не выполнялась»).

См. docs/v0-findings.md для полного, честного описания: реальные ошибки, найденные и исправленные при валидации, сравнение по уровням моделей и что ещё остаётся открытым.

Лицензия

MIT

Available Tools

6 tools
crawl_siteCrawl siteB

Playwright headless crawl of reachable routes. Emits periodic progress notifications.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesBase URL to crawl
maxPagesNoOptional cap on how many reachable pages to visit. Unset means no limit.
repoPathYesRepo path whose .dossier/ this crawl evidence should be saved under

Output Schema

ParametersJSON Schema
NameRequiredDescription
savedToYes
openCasesYes
routesVisitedYes
routesWithConsoleErrorsYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotency, and destructive hints. The description adds some behavioral detail by noting it runs headless and emits periodic progress notifications, but it does not clarify what side effects the crawl may produce beyond visiting pages, even though readOnlyHint is false and repoPath suggests saving evidence. No contradiction with annotations was found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no filler, and the core action is front-loaded. It is concise and readable, though it could have used the extra space to provide more usage context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the schema fully documents all parameters and an output schema exists, the core technical details are covered. However, the description alone does not address when to use the tool, what side effects the crawl might have, or how it relates to the sibling tools. It is adequate but has clear gaps for an agent deciding whether to invoke it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains url, maxPages, and repoPath. The description does add a small hint that the crawl follows reachable routes from the base URL, but it does not materially improve on the parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('crawl'), the resource ('site'), and the method ('Playwright headless'), and specifies the scope as 'reachable routes.' This distinguishes it from the sibling tools, which perform different operations like ingesting, flagging, or resolving.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to choose this tool over alternatives, no prerequisites, and no exclusions. The intended context is only implied by the word 'crawl,' not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

flag_known_bugFlag known bugA

Record a known bug. Always overrides auto-resolve for any case it matches, regardless of other evidence.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoPathYesRepo path whose .dossier/ this known bug belongs to
descriptionYesFree-text description of a known bug, stored verbatim

Output Schema

ParametersJSON Schema
NameRequiredDescription
bugYes
openCasesYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only indicate that this is a non-read-only, non-idempotent mutation. The description adds the crucial non-obvious behavior that a flagged known bug always wins over auto-resolve regardless of evidence. This is valuable context that annotations cannot communicate. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The primary action is front-loaded, followed immediately by the single most important behavioral rule. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter write tool, the description covers the action and the essential override behavior, and the schema documents the parameters. An output schema exists, so return-value details are not needed. The only small gap is that when-to-use guidance is implied rather than explicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and both parameters (repoPath and description) are already well documented in the schema. The main description adds no additional parameter semantics, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Record a known bug') and immediately supplies the core differentiator: it overrides auto-resolve. This distinguishes it from sibling resolution/auto-resolve tools without needing to inspect the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The second sentence gives a clear behavioral context: use this when a known bug should supersede any auto-resolve conclusion, even when other evidence points elsewhere. It does not explicitly list when not to use it or name sibling tools, but the precedence rule strongly implies the intended usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_specGenerate specA
Destructive

Write CLAUDE.md, .claude/, spec/, tests/, and kickoff-prompt.txt to -rebuild/. Only callable once the case queue is empty. Optional: if the target is a Next.js app with page routes, set GROQ_API_KEY and REBUILD_DOSSIER_ENABLE_VISION_CLASSIFICATION=1 before calling this tool to enable vision-assisted page-content classification (sends each captured page's screenshot and source code to Groq to judge static vs. dynamic content more accurately than plain regex matching) — ask the user for a Groq API key if they want more reliable generated page tests and this isn't already configured. Off by default; nothing changes if unset. Optional: pass authStorageStatePath to reach auth-gated pages during capture — see that field's own description for how to produce it.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoPathYesRepo path that was ingested; output is written to a sibling <repoPath>-rebuild/ directory
authStorageStatePathNoOptional path to a Playwright storageState JSON file (cookies/localStorage from an already-authenticated session against the target app) — load it once with `npx playwright open <url> --save-storage=state.json` after logging in by hand, or any equivalent one-time export. When set, page capture uses it to reach auth-gated pages instead of only ever seeing a login screen; this tool never logs in itself or handles credentials. The file is copied into the rebuild output (tests/fixtures/auth-storage-state.json, gitignored) so generated page tests can reach the same pages when run standalone.

Output Schema

ParametersJSON Schema
NameRequiredDescription
warningNo
outputDirYes
weakTestsYes
skippedPagesYes
capturedPagesYes
pageCaptureNoteNo
unrunnableTestsYes
mutationsCheckedYes
pageVisionFallbacksNo
pageVisionFallbackNoteNo
visionClassificationNoteNo
visionClassificationEnabledYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations already marking this as destructive and non-read-only, the description adds substantial behavioral context: the tool is only callable with an empty case queue, the vision mode is off by default and changes nothing when unset, the tool never logs in or handles credentials itself, and the auth state file is copied into build output and gitignored. These details meaningfully extend beyond the annotation hints and help an agent predict side effects and prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action, then moves from precondition to optional enhancements in a logical order. Every sentence carries operational weight: the initial write target, the queue precondition, the vision-mode toggle and tradeoff, and the auth-state option. Although it is longer than a one-liner, the length is justified by the conditional behavior it must convey.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description, annotations, and rich schema collectively cover prerequisites, optional configurations, credential handling, side-effect locations, and output scope. Since an output schema exists, the description does not need to detail return values. There is no obvious gap an agent would need to guess about in order to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already fully documents repoPath and authStorageStatePath. The tool description adds only a cross-reference to authStorageStatePath and an optional storage-state usage note, but does not go beyond what the schema fields themselves say. With high schema coverage, baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: it writes CLAUDE.md, .claude/, spec/, tests/, and kickoff-prompt.txt to a <repo>-rebuild/ directory. This clearly distinguishes it from sibling tools like ingest_repo or crawl_site, which perform other pipeline stages. The title alone would be vague, but the description removes all ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states an explicit precondition: 'Only callable once the case queue is empty,' which tells the agent when it may and may not be invoked. It also provides conditional guidance for two optional modes: when to set the vision-classification env vars, when to ask the user for a Groq key, and when to pass authStorageStatePath. This is direct, operational usage guidance rather than left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_case_queueGet case queueB
Destructive

Return unresolved ambiguity cases from reconciliation.

ParametersJSON Schema
NameRequiredDescriptionDefault
repoPathYesRepo path whose .dossier/ case queue to read
interactiveNoWhen true, walk open cases via MCP elicitation instead of just listing them

Output Schema

ParametersJSON Schema
NameRequiredDescription
openYes
casesYes

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true and readOnlyHint=false, but the description's 'Return...' reads as a safe read operation and adds no context about side effects, what may be destroyed, or why the tool is marked destructive. This mismatch makes the safety profile confusing and under-disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one short sentence with no filler. It front-loads the core purpose, and every word contributes to understanding what the tool returns.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The schema covers parameters and an output schema exists, so return structure is not the description's burden. However, the description is too thin to fully explain the disruptive destructive hint, the reconciliation context, or when an agent should prefer resolve_case, leaving the overall guidance minimally viable but gapped.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so repoPath and interactive are already documented in the schema. The description adds no extra parameter meaning beyond the schema and does not address the interactive behavior or its consequences.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Return unresolved ambiguity cases from reconciliation' uses a specific verb and resource, making the tool's main output clear. It is distinguishable from siblings like resolve_case, but it does not explicitly call out that distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description only implies when to use the tool: when unresolved ambiguity cases from reconciliation need to be retrieved. It gives no guidance about alternatives such as resolve_case, nor any exclusions, leaving the agent to infer selection criteria from the name and schema.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ingest_repoIngest repoA
Idempotent

Parse package.json, tailwind/vite config, route files, and existing tests via static analysis. No LLM call.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to the repo to ingest
interactiveNoWhen true and 0 routes are found at a monorepo-shaped path, ask via elicitation which candidate directory is the real app, then ingest that instead

Output Schema

ParametersJSON Schema
NameRequiredDescription
routesYes
savedToYes
signalsYes
openCasesYes
buildConfigYes
monorepoHintNo
existingTestsYes
resolvedMonorepoChoiceNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide idempotentHint=true and destructiveHint=false. The description adds meaningful behavioral context with 'static analysis' and 'No LLM call', signaling deterministic, non-LLM execution beyond what annotations state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The first states the operation and scope, and the second adds a key behavioral constraint. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is low complexity, has full schema coverage, an output schema, and annotations covering idempotency and destructiveness. The description supplies the remaining essential facts: what files are parsed and that no LLM call is made.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both path and interactive are already well documented in the input schema. The description does not add parameter-specific meaning, which is acceptable given the schema already carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb, 'Parse', and names concrete resources: package.json, tailwind/vite config, route files, and existing tests. An agent can tell what the tool operates on, though it does not explicitly contrast itself with siblings like generate_spec or crawl_site.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The static-analysis phrasing and 'No LLM call' imply this is a deterministic, lower-cost ingestion step, but the description does not explicitly say when to use this tool versus alternatives. Sibling names provide context, yet no direct routing or exclusion guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_caseResolve caseA
DestructiveIdempotent

Resolve one open case with a human decision. Always available, no elicitation capability required.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe case id to resolve, as returned by get_case_queue (e.g. "case:...")
noteNoOptional free-text note explaining the decision
decisionYesFree-text decision, e.g. "intentional" or "bug" — stored verbatim, not a fixed enum
repoPathYesRepo path whose .dossier/ this case belongs to

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
statusYes
signalsYes
conflictNo
topicKeyYes
humanDecisionNo
autoResolutionNo
relatedCaseIdsNo
matchedKnownBugsYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry the safety profile (destructiveHint=true, idempotentHint=true), and the description adds the useful operational trait that the tool is always available and requires no elicitation capability. It does not, however, disclose what resolution actually changes (e.g., case status or removal from the queue), leaving the side effect only implied by the destructive hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences, front-loaded with the primary purpose and followed by a concise availability note. Every word earns its place; there is no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool benefits from rich annotations, 100% parameter documentation, and an output schema, so the description need not explain return values. Still, it omits the practical effect of resolving a case (e.g., the case disappearing from get_case_queue) and provides no guidance about when to prefer this over the closely related sibling flag_known_bug, leaving a small but real completeness gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline is 3. The description adds the key semantic that the decision must be a human decision, which is not stated in the schema's decision property text and helps prevent an agent from fabricating a decision on its own. This one meaningful addition justifies a score above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'resolve one open case' with the key qualifier 'with a human decision.' It is not a tautology and clearly outlines the core action, but it does not explicitly contrast with sibling tools like flag_known_bug or get_case_queue, so it falls short of full differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Always available, no elicitation capability required' gives some operational context about when the tool can be invoked, implying it is the standard path for resolving a case. However, it never names alternatives or conditions when another sibling should be used instead, so guidance is mostly implicit rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.2.6-paper
    • Changedcrawl_site2 fields changed
      • addedInput schema / properties / maxPages / description
        Added value: +"Optional cap on how many reachable pages to visit. Unset means no limit."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "openCases": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "routesVisited": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "routesWithConsoleErrors": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "savedTo": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "routesVisited",
        +    "routesWithConsoleErrors",
        +    "openCases",
        +    "savedTo"
        +  ],
        +  "type": "object"
        +}
    • Changedflag_known_bug1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "bug": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "description": {
        +          "type": "string"
        +        },
        +        "flaggedAt": {
        +          "type": "string"
        +        },
        +        "id": {
        +          "type": "string"
        +        },
        +        "matchHints": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "id",
        +        "description",
        +        "matchHints",
        +        "flaggedAt"
        +      ],
        +      "type": "object"
        +    },
        +    "openCases": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "bug",
        +    "openCases"
        +  ],
        +  "type": "object"
        +}
    • Changedgenerate_spec1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "capturedPages": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "mutationsChecked": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "outputDir": {
        +      "type": "string"
        +    },
        +    "pageCaptureNote": {
        +      "type": "string"
        +    },
        +    "pageVisionFallbackNote": {
        +      "type": "string"
        +    },
        +    "pageVisionFallbacks": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "reason": {
        +            "type": "string"
        +          },
        +          "routeFile": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "routeFile",
        +          "reason"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "skippedPages": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "reason": {
        +            "type": "string"
        +          },
        +          "routeFile": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "routeFile",
        +          "reason"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "unrunnableTests": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "visionClassificationEnabled": {
        +      "type": "boolean"
        +    },
        +    "visionClassificationNote": {
        +      "type": "string"
        +    },
        +    "warning": {
        +      "type": "string"
        +    },
        +    "weakTests": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "outputDir",
        +    "mutationsChecked",
        +    "weakTests",
        +    "unrunnableTests",
        +    "capturedPages",
        +    "skippedPages",
        +    "visionClassificationEnabled"
        +  ],
        +  "type": "object"
        +}
    • Changedget_case_queue1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "cases": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "autoResolution": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decision": {
        +                "enum": [
        +                  "intentional",
        +                  "bug"
        +                ],
        +                "type": "string"
        +              },
        +              "reason": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "decision",
        +              "reason"
        +            ],
        +            "type": "object"
        +          },
        +          "conflict": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "detail": {
        +                "type": "string"
        +              },
        +              "kind": {
        +                "enum": [
        +                  "known_bug_vs_intentional_evidence",
        +                  "signal_disagreement"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "kind",
        +              "detail"
        +            ],
        +            "type": "object"
        +          },
        +          "humanDecision": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "decidedAt": {
        +                "type": "string"
        +              },
        +              "decision": {
        +                "type": "string"
        +              },
        +              "note": {
        +                "type": "string"
        +              },
        +              "via": {
        +                "enum": [
        +                  "elicitation",
        +                  "resolve_case_tool"
        +                ],
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "decision",
        +              "decidedAt",
        +              "via"
        +            ],
        +            "type": "object"
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "matchedKnownBugs": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "relatedCaseIds": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "signals": {
        +            "items": {
        +              "additionalProperties": false,
        +              "properties": {
        +                "affirmativeIntent": {
        +                  "additionalProperties": false,
        +                  "properties": {
        +                    "confidence": {
        +                      "maximum": 1,
        +                      "minimum": 0,
        +                      "type": "number"
        +                    },
        +                    "kind": {
        +                      "enum": [
        +                        "comment",
        +                        "docstring",
        +                        "todo",
        +                        "fixme"
        +                      ],
        +                      "type": "string"
        +                    },
        +                    "locator": {
        +                      "additionalProperties": false,
        +                      "properties": {
        +                        "endLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        },
        +                        "file": {
        +                          "type": "string"
        +                        },
        +                        "startLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        }
        +                      },
        +                      "required": [
        +                        "file",
        +                        "startLine",
        +                        "endLine"
        +                      ],
        +                      "type": "object"
        +                    },
        +                    "text": {
        +                      "type": "string"
        +                    }
        +                  },
        +                  "required": [
        +                    "kind",
        +                    "text",
        +                    "locator",
        +                    "confidence"
        +                  ],
        +                  "type": "object"
        +                },
        +                "claim": {
        +                  "type": "string"
        +                },
        +                "detectedAt": {
        +                  "type": "string"
        +                },
        +                "evidenceText": {
        +                  "type": "string"
        +                },
        +                "id": {
        +                  "type": "string"
        +                },
        +                "locator": {
        +                  "anyOf": [
        +                    {
        +                      "additionalProperties": false,
        +                      "properties": {
        +                        "endLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        },
        +                        "file": {
        +                          "type": "string"
        +                        },
        +                        "startLine": {
        +                          "maximum": 9007199254740991,
        +                          "minimum": -9007199254740991,
        +                          "type": "integer"
        +                        }
        +                      },
        +                      "required": [
        +                        "file",
        +                        "startLine",
        +                        "endLine"
        +                      ],
        +                      "type": "object"
        +                    },
        +                    {
        +                      "additionalProperties": false,
        +                      "properties": {
        +                        "method": {
        +                          "type": "string"
        +                        },
        +                        "path": {
        +                          "type": "string"
        +                        }
        +                      },
        +                      "required": [
        +                        "path"
        +                      ],
        +                      "type": "object"
        +                    }
        +                  ]
        +                },
        +                "source": {
        +                  "enum": [
        +                    "ingest",
        +                    "crawl",
        +                    "known_bug"
        +                  ],
        +                  "type": "string"
        +                },
        +                "topicKey": {
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "id",
        +                "source",
        +                "locator",
        +                "topicKey",
        +                "claim",
        +                "evidenceText",
        +                "detectedAt"
        +              ],
        +              "type": "object"
        +            },
        +            "type": "array"
        +          },
        +          "status": {
        +            "enum": [
        +              "auto_resolved",
        +              "open",
        +              "resolved_by_human"
        +            ],
        +            "type": "string"
        +          },
        +          "topicKey": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "topicKey",
        +          "signals",
        +          "matchedKnownBugs",
        +          "status"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "open": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "open",
        +    "cases"
        +  ],
        +  "type": "object"
        +}
    • Changedingest_repo1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "buildConfig": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "existingTests": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "monorepoHint": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "candidates": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "message": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "message",
        +        "candidates"
        +      ],
        +      "type": "object"
        +    },
        +    "openCases": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "resolvedMonorepoChoice": {
        +      "type": "string"
        +    },
        +    "routes": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "savedTo": {
        +      "type": "string"
        +    },
        +    "signals": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "routes",
        +    "existingTests",
        +    "signals",
        +    "buildConfig",
        +    "openCases",
        +    "savedTo"
        +  ],
        +  "type": "object"
        +}
    • Changedresolve_case4 fields changed
      • addedInput schema / properties / decision / description
        Added value: +"Free-text decision, e.g. \"intentional\" or \"bug\" — stored verbatim, not a fixed enum"
      • addedInput schema / properties / id / description
        Added value: +"The case id to resolve, as returned by get_case_queue (e.g. \"case:...\")"
      • addedInput schema / properties / note / description
        Added value: +"Optional free-text note explaining the decision"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "https://json-schema.org/draft/2020-12/schema",
        +  "additionalProperties": false,
        +  "properties": {
        +    "autoResolution": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "decision": {
        +          "enum": [
        +            "intentional",
        +            "bug"
        +          ],
        +          "type": "string"
        +        },
        +        "reason": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "decision",
        +        "reason"
        +      ],
        +      "type": "object"
        +    },
        +    "conflict": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "detail": {
        +          "type": "string"
        +        },
        +        "kind": {
        +          "enum": [
        +            "known_bug_vs_intentional_evidence",
        +            "signal_disagreement"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "kind",
        +        "detail"
        +      ],
        +      "type": "object"
        +    },
        +    "humanDecision": {
        +      "additionalProperties": false,
        +      "properties": {
        +        "decidedAt": {
        +          "type": "string"
        +        },
        +        "decision": {
        +          "type": "string"
        +        },
        +        "note": {
        +          "type": "string"
        +        },
        +        "via": {
        +          "enum": [
        +            "elicitation",
        +            "resolve_case_tool"
        +          ],
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "decision",
        +        "decidedAt",
        +        "via"
        +      ],
        +      "type": "object"
        +    },
        +    "id": {
        +      "type": "string"
        +    },
        +    "matchedKnownBugs": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "relatedCaseIds": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "signals": {
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "affirmativeIntent": {
        +            "additionalProperties": false,
        +            "properties": {
        +              "confidence": {
        +                "maximum": 1,
        +                "minimum": 0,
        +                "type": "number"
        +              },
        +              "kind": {
        +                "enum": [
        +                  "comment",
        +                  "docstring",
        +                  "todo",
        +                  "fixme"
        +                ],
        +                "type": "string"
        +              },
        +              "locator": {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "endLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  },
        +                  "file": {
        +                    "type": "string"
        +                  },
        +                  "startLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  }
        +                },
        +                "required": [
        +                  "file",
        +                  "startLine",
        +                  "endLine"
        +                ],
        +                "type": "object"
        +              },
        +              "text": {
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "kind",
        +              "text",
        +              "locator",
        +              "confidence"
        +            ],
        +            "type": "object"
        +          },
        +          "claim": {
        +            "type": "string"
        +          },
        +          "detectedAt": {
        +            "type": "string"
        +          },
        +          "evidenceText": {
        +            "type": "string"
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "locator": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "endLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  },
        +                  "file": {
        +                    "type": "string"
        +                  },
        +                  "startLine": {
        +                    "maximum": 9007199254740991,
        +                    "minimum": -9007199254740991,
        +                    "type": "integer"
        +                  }
        +                },
        +                "required": [
        +                  "file",
        +                  "startLine",
        +                  "endLine"
        +                ],
        +                "type": "object"
        +              },
        +              {
        +                "additionalProperties": false,
        +                "properties": {
        +                  "method": {
        +                    "type": "string"
        +                  },
        +                  "path": {
        +                    "type": "string"
        +                  }
        +                },
        +                "required": [
        +                  "path"
        +                ],
        +                "type": "object"
        +              }
        +            ]
        +          },
        +          "source": {
        +            "enum": [
        +              "ingest",
        +              "crawl",
        +              "known_bug"
        +            ],
        +            "type": "string"
        +          },
        +          "topicKey": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "source",
        +          "locator",
        +          "topicKey",
        +          "claim",
        +          "evidenceText",
        +          "detectedAt"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "enum": [
        +        "auto_resolved",
        +        "open",
        +        "resolved_by_human"
        +      ],
        +      "type": "string"
        +    },
        +    "topicKey": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "topicKey",
        +    "signals",
        +    "matchedKnownBugs",
        +    "status"
        +  ],
        +  "type": "object"
        +}
  2. 1 tool updatev0.2.2-paper
    • Changedgenerate_spec1 field changed
      • addedInput schema / properties / authStorageStatePath
        Added value: +{
        +  "description": "Optional path to a Playwright storageState JSON file (cookies/localStorage from an already-authenticated session against the target app) — load it once with `npx playwright open <url> --save-storage=state.json` after logging in by hand, or any equivalent one-time export. When set, page capture uses it to reach auth-gated pages instead of only ever seeing a login screen; this tool never logs in itself or handles credentials. The file is copied into the rebuild output (tests/fixtures/auth-storage-state.json, gitignored) so generated page tests can reach the same pages when run standalone.",
        +  "type": "string"
        +}
  3. 6 tool updatesv0.2.0
    • First observedcrawl_site
    • First observedflag_known_bug
    • First observedgenerate_spec
    • First observedget_case_queue
    • First observedingest_repo
    • First observedresolve_case

TDQS

A4/5.0
Disambiguation5/5

Each tool has a clearly distinct role in the pipeline: static repo ingestion, dynamic site crawling, recording a known bug override, listing unresolved cases, resolving a case, and generating the final dossier. There is no functional overlap or ambiguity between tool boundaries.

Naming Consistency5/5

All six tool names follow the same snake_case verb_noun convention, such as ingest_repo, crawl_site, get_case_queue, and generate_spec. The verb choices are specific and the object naming is consistent, making the set predictable and easy to navigate.

Tool Count5/5

Six tools is a well-scoped size for this workflow, covering ingestion, crawling, bug flagging, case management, and final generation without redundancy. Each tool maps to a necessary step in the rebuild-dossier process and fits comfortably within the ideal range.

Completeness4/5

The main workflow is well covered: static analysis, dynamic crawling, human-in-the-loop case resolution, and final spec generation are all present. A minor gap is that there is no tool to list or remove previously flagged known bugs, but this does not prevent completing the core pipeline.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server that spawns autonomous Claude Code agents in GitHub repos, enabling task delegation with persistent state, multi-step workflows, and job monitoring.
    47
    94
    2
    Apache 2.0
  • F
    license
    A
    quality
    D
    maintenance
    A safe, local MCP server that lets Claude drive a controlled software-development loop (inspect, read, plan, patch, apply, check, analyze, fix, summarize) on a project, using deterministic tools and real diffs/test runs.
    10
    1
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Parker-Fawcett/rebuild-dossier'

If you have feedback or need assistance with the MCP directory API, please join our Discord server