Test the spec guard and the linkage linter #44

Open
opened 2026-08-10 13:10:11 +00:00 by claude · 0 comments
Collaborator

Summary

Покрыть тестами hooks/spec-guard.sh и линтер связки спека ↔ тест-кейс ↔ тест.

Spec

AGENTS.md

Depends on

  • gate-openspec-changes-onto-a-worktree — нечего тестировать, пока хука нет
  • lint-the-spec-to-test-linkage — то же для линтера

Motivation

У хуков в этой репе нет прецедента тестирования: hooks/tea-guard.sh не покрыт,
хотя это единственная деталь, которая молча переписывает чужую команду.

spec-guard.sh опаснее: он не только блокирует, но и создаёт worktree.
Ошибка в определении текущей ветки или в проверке грязи ломает каждый propose, и
ломает молча — модель получит блок и уйдёт делать что-то другое.

Линтер держит формат TC в одиночку — openspec, как показала проба, не проверяет
внутренность сценария вообще. Непокрытый линтер означает, что связку не
проверяет никто.

Test cases

Хук:

  • payload не про openspec → passthrough, exit 0, пустой stdout
  • openspec не найден в PATH → passthrough
  • в корне репозитория нет openspec/ → passthrough
  • текущая ветка не main → passthrough
  • main, есть tracked-модификация → exit 2, stderr называет и commit, и stash
  • main, есть только untracked-файлы → не блокирует
  • чистый main, openspec new change x → worktree создан, exit 2, stderr
    содержит путь worktree и вызов EnterWorktree
  • ветка feat/x уже существует → exit 2, worktree не создан
  • путь ../tea-worktrees/x занят → exit 2, worktree не создан
  • openspec archive не на main → exit 2
  • openspec archive на чистом main → passthrough

Линтер:

  • сценарий без **TEST** → exit 1 с путём и номером строки
  • сценарий без **WHEN** или без **THEN** → exit 1
  • два **TEST** в одном сценарии → exit 1
  • TC id не матчит TC-[A-Z]+-\d{3} → exit 1
  • один TC встречается и в change, и в архивной спеке → exit 1
  • TC есть в спеке, отсутствует в tests.md → exit 1
  • TC есть в tests.md, отсутствует в docstring теста → exit 1
  • согласованное дерево → exit 0

Acceptance criteria

  • все перечисленные кейсы покрыты в tests/, и
    python3 -m unittest discover -s tests зелёный
  • тест хука строит одноразовый репозиторий в
    tempfile.TemporaryDirectory() и запускает хук подпроцессом, подавая
    payload в stdin
  • ни один тест не трогает tmp/issues/ и tmp/wiki/
  • ни один тест не создаёт worktree в настоящем репозитории и не оставляет
    записей в его git worktree list
  • тесты только на stdlib unittest, без зависимостей

Constraints

  • Не входит в объём: покрыть тестами hooks/tea-guard.sh. Долг реальный, но это
    другой issue и другой хук.
  • Не входит в объём: интеграционный прогон openspec как процесса. Тестируем
    свой код, не пакет.
<!-- tea:id test-the-spec-guard-and-the-linkage-linter --> ## Summary Покрыть тестами `hooks/spec-guard.sh` и линтер связки спека ↔ тест-кейс ↔ тест. ## Spec `AGENTS.md` ## Depends on - gate-openspec-changes-onto-a-worktree — нечего тестировать, пока хука нет - lint-the-spec-to-test-linkage — то же для линтера ## Motivation У хуков в этой репе нет прецедента тестирования: `hooks/tea-guard.sh` не покрыт, хотя это единственная деталь, которая молча переписывает чужую команду. `spec-guard.sh` опаснее: он не только блокирует, но и **создаёт worktree**. Ошибка в определении текущей ветки или в проверке грязи ломает каждый propose, и ломает молча — модель получит блок и уйдёт делать что-то другое. Линтер держит формат TC в одиночку — openspec, как показала проба, не проверяет внутренность сценария вообще. Непокрытый линтер означает, что связку не проверяет никто. ## Test cases Хук: - payload не про openspec → passthrough, exit 0, пустой stdout - `openspec` не найден в PATH → passthrough - в корне репозитория нет `openspec/` → passthrough - текущая ветка не main → passthrough - main, есть tracked-модификация → exit 2, stderr называет и commit, и stash - main, есть только untracked-файлы → не блокирует - чистый main, `openspec new change x` → worktree создан, exit 2, stderr содержит путь worktree и вызов `EnterWorktree` - ветка `feat/x` уже существует → exit 2, worktree не создан - путь `../tea-worktrees/x` занят → exit 2, worktree не создан - `openspec archive` не на main → exit 2 - `openspec archive` на чистом main → passthrough Линтер: - сценарий без `**TEST**` → exit 1 с путём и номером строки - сценарий без `**WHEN**` или без `**THEN**` → exit 1 - два `**TEST**` в одном сценарии → exit 1 - TC id не матчит `TC-[A-Z]+-\d{3}` → exit 1 - один TC встречается и в change, и в архивной спеке → exit 1 - TC есть в спеке, отсутствует в `tests.md` → exit 1 - TC есть в `tests.md`, отсутствует в docstring теста → exit 1 - согласованное дерево → exit 0 ## Acceptance criteria - [ ] все перечисленные кейсы покрыты в `tests/`, и `python3 -m unittest discover -s tests` зелёный - [ ] тест хука строит одноразовый репозиторий в `tempfile.TemporaryDirectory()` и запускает хук подпроцессом, подавая payload в stdin - [ ] ни один тест не трогает `tmp/issues/` и `tmp/wiki/` - [ ] ни один тест не создаёт worktree в настоящем репозитории и не оставляет записей в его `git worktree list` - [ ] тесты только на stdlib `unittest`, без зависимостей ## Constraints - Не входит в объём: покрыть тестами `hooks/tea-guard.sh`. Долг реальный, но это другой issue и другой хук. - Не входит в объём: интеграционный прогон `openspec` как процесса. Тестируем свой код, не пакет.
claude added this to the openspec integration milestone 2026-08-10 13:10:11 +00:00
claude added the
type
test
comp/hookscomp/openspec
labels 2026-08-10 13:10:11 +00:00
claude added a new dependency 2026-08-10 13:10:11 +00:00
claude added a new dependency 2026-08-10 13:10:11 +00:00
claude added a new dependency 2026-08-10 13:10:13 +00:00
Sign in to join this conversation.