---
description: Автоматичний збір ADR/Runbook/Knowledge-чернеток і батч-нормалізація у `docs/adr/` через Stop-хуки Claude Code та Cursor Agent
alwaysApply: true
version: '2.2'
---

Правило `adr` автоматично фіксує архітектурні рішення (ADR) після кожної сесії через Stop-хуки і батч-нормалізує чернетки у канонічний формат MADR v4.

## Stop-hook у `.claude/settings.json`

Канонічний запис, який вставляє sync (поряд із PostToolUse fix-хуком — той живе в іншій події, тут не показаний):

```json title=".claude/settings.json"
{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/capture-decisions.sh\"",
            "async": true,
            "timeout": 180
          }
        ]
      },
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/normalize-decisions.sh\"",
            "async": true,
            "timeout": 600
          }
        ]
      }
    ]
  }
}
```

Обидві ADR-групи ідентифікуються пакетом за маркером у `command` (`.claude/hooks/capture-decisions.sh`, `.claude/hooks/normalize-decisions.sh`) — користувацькі hook-групи поряд не чіпаються. Якщо `adr` прибрати з `rules`, обидві ADR-групи автоматично видаляються на наступному `npx @7n/rules`.

## Stop-hook у `.cursor/hooks.json`

Cursor Agent читає project-level **`.cursor/hooks.json`**. `npx @7n/rules` merge-ить файл: користувацькі hooks лишаються, managed entries для `capture-decisions.sh` і `normalize-decisions.sh` перезаписуються або видаляються разом із правилом `adr`.

```json title=".cursor/hooks.json"
{
  "version": 1,
  "hooks": {
    "stop": [
      {
        "command": "bash -lc 'root=\"$PWD\"; if [ ! -f \"$root/.claude/hooks/capture-decisions.sh\" ] && [ -f \"$root/../.claude/hooks/capture-decisions.sh\" ]; then root=\"$root/..\"; fi; bash \"$root/.claude/hooks/capture-decisions.sh\"'",
        "timeout": 180
      },
      {
        "command": "bash -lc 'root=\"$PWD\"; if [ ! -f \"$root/.claude/hooks/normalize-decisions.sh\" ] && [ -f \"$root/../.claude/hooks/normalize-decisions.sh\" ]; then root=\"$root/..\"; fi; bash \"$root/.claude/hooks/normalize-decisions.sh\"'",
        "timeout": 600
      }
    ]
  }
}
```

Обидва Stop-hook'и ADR живуть у **project-shared** `.claude/settings.json` (закомічений), щоб механізм працював у всіх членів команди. Якщо хук колись був у `.claude/settings.local.json` — прибери дубль вручну: project-shared і local-копія створили б два запуски на одну подію.

## ADR_HOOKS_SKIP — оркестраторні сесії не потрапляють у ADR hooks

Підкоманди-оркестратори (`npx @7n/rules lint`, `/n-lint`, `/n-doc-files`, `/n-taze`, `/n-release` тощо) можуть спавнити внутрішню agent/LLM-сесію. Такий транскрипт — технічний шум, не людська думка, тому JS-оркестратор (`npm/bin/n-rules.js`) виставляє `ADR_HOOKS_SKIP=1` перед `switch (command)`, до будь-якого дочірнього процесу. `capture-decisions.sh`, `normalize-decisions.sh` і `pi`-extension (`n-rules-adr`) перевіряють прапор одразу після власних recursion guards і мовчки виходять (`exit 0` / `return`) — без запису в лог.

## Capture-бекенд: `CAPTURE_DECISIONS_BACKEND`

`capture-decisions.sh` вибирає LLM-бекенд через env-селектор (дефолт `pi`):

| Значення | Поведінка |
| --- | --- |
| `pi` (дефолт) | Тільки локальний `pi` (npm-first lookup: root `.bin`, nested `@7n/rules` `.bin`, `PATH`); без бінарника або без моделі (`CAPTURE_DECISIONS_PI_MODEL`/`N_LOCAL_MIN_MODEL`) — мовчки `exit 0`, без cloud-фолбеку |
| `claude` | Примусово `claude -p --model "$CAPTURE_DECISIONS_CLAUDE_MODEL"` |
| `cursor-agent` | Примусово `cursor-agent -p --mode ask --model "$CAPTURE_DECISIONS_CURSOR_MODEL"` |
| `auto` | Каскад за доступністю: `pi` -> `claude` -> `cursor-agent` -> skip (не за результатом виклику — порожня відповідь обраного бекенду фінальна) |

Дефолт `pi` тримає capture локальним і безкоштовним; cloud вмикається лише свідомим `CAPTURE_DECISIONS_BACKEND=auto` (або `claude`/`cursor-agent`). Виклик `pi` герметичний і офлайн: `--no-session --mode text --no-tools --no-context-files --no-extensions --no-skills --no-prompt-templates --offline`.

## Швидкий gate через conftest

| Namespace | Файл | Що перевіряє |
| --- | --- | --- |
| `adr.settings_json` | `.claude/settings.json` | Наявність обох Stop-хуків у `hooks.Stop[]` |
| `adr.settings_local_json` | `.claude/settings.local.json` | Відсутність дублів Stop-хуків у local-файлі |

