CLAUDE.md@skills/init/templates · git:20260907.ad5db37 · 2026-09-07 · sha256 f8a85cb0c186555a

CLAUDE.md@skills/init/templates git:20260907.ad5db37B

Immutable. This exact content is served forever at /api/v1/blob/f8a85cb0c186555a.

# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

---

# Polisade Orchestrator — Autonomous Development Framework

This project uses the **Polisade Orchestrator** plugin (part of the Polisade toolchain; technical id: `polisade`) for running Claude as an autonomous development team. PM interacts through natural language or explicit `/polisade:*` slash commands.

## Core Concept

Claude operates autonomously, executing a full development cycle: implement → test → PR → review → merge. PM intervenes only for business decisions, unclear requirements, or architectural choices with significant consequences.

## Natural Language Interface

PM can communicate in natural language. Claude recognizes intent and executes the appropriate command.

| PM Says | Intent | Command |
|---------|--------|---------|
| "Статус?" / "What's the project status?" | status | `/polisade:state` |
| "Кнопка не работает" / "Button broken" | defect | `/polisade:defect` |
| "Нужен экспорт в PDF" / "Need PDF export" | feature | `/polisade:feature` |
| "Новый модуль аналитики" | prd | `/polisade:prd` |
| "Поменяй конфиг" / "Update config" | chore | `/polisade:chore` |
| "Надо отрефакторить" / "Need to refactor" | debt | `/polisade:debt` |
| "Какую библиотеку выбрать?" | spike | `/polisade:spike` |
| "Работай" / "Continue" | continue | `/polisade:continue` |
| "Что ждёт моего ответа?" | unblock | `/polisade:unblock` |
| "Какие вопросы открыты?" / "Open questions?" | questions | `/polisade:questions` |

If intent is ambiguous, ask a clarifying question.

## Three Work Levels

### 1. Large Initiatives (epics, new modules)
```
/polisade:prd → /polisade:spec → /polisade:design → /polisade:roadmap → /polisade:tasks → /polisade:continue
                              (опционально)
```

`/polisade:design` — опциональный шаг для создания doc-as-code артефактов (C4 диаграммы, ER, OpenAPI, ADR, glossary). Запускай для новых модулей, архитектурных переписываний, перед передачей SPEC другой команде. Для простых фич можно пропускать.

### 2. Regular Features
```
/polisade:feature → /polisade:tasks → /polisade:continue
              ↘ /polisade:spec (if complex) → /polisade:tasks → /polisade:continue
```

### 3. Bugs, Tech Debt, Chores
```
/polisade:defect → auto-creates TASK → /polisade:continue
/polisade:debt   → регистрация (без TASK по умолчанию)
             ↘ --task или /polisade:tasks DEBT-XXX → TASK → /polisade:continue
/polisade:chore  → CHORE + TASK → /polisade:continue
             ↘ --no-task → только CHORE (регистрация)
```

**IMPORTANT:** `/polisade:implement` accepts ONLY `TASK-XXX`. BUG creates linked TASK
automatically. DEBT creates TASK only on opt-in (`--task` flag or
`settings.debt.autoCreateTask: true`). CHORE creates TASK by default;
`--no-task` opts out.

## Full Autonomous Cycle

**⛔ CRITICAL: `/polisade:implement` and `/polisade:continue` behave DIFFERENTLY!**

| Aspect | /polisade:implement | /polisade:continue |
|--------|-----------------|----------------|
| Tasks count | **ONE** | All ready |
| After merge | **STOP** | Next task |
| Use case | Controlled execution | Autonomous work |
| PM control | After each task | Only when blocked |

### Cycle for ONE task (/polisade:implement)

> **Note:** `/polisade:continue` has its own cycle definition and may not yet
> support TDD-first. A separate redesign is planned.

```
1. IMPLEMENT → Create branch
   • If testing.strategy: "tdd-first" (default):
     1a. TEST-FIRST → Failing tests from AC/Gherkin, RED CHECKLIST, commit
     1b. CODE → Implement to pass tests, SELF-REVIEW CHECKLIST, commit
   • If testing.strategy: "test-along":
     Code + unit tests simultaneously, SELF-REVIEW CHECKLIST, commit
2. REGRESSION TEST → Run ALL project tests, fix if failing, repeat
   + Drift gate: `${POLISADE_PYTHON:-python3} scripts/polisade_drift_gate.py` (if present) —
     deterministic arch↔code check, exit≠0 = regression, fix BEFORE PR
3. CREATE PR → Push branch, create PR, status → review
4. QUALITY REVIEW → Independent review (auto-detected: Codex CLI if installed, otherwise current agent CLI via `self`)
   → Reviewer scores PR diff vs TASK requirements (1-10)
   → Score >= 8: PASS → merge
   → Score < 8: IMPROVE → improvement subagent fixes → re-review (max 2 iterations)
   → After 2 iterations with score < 8: STOP → waiting_pm (PM decides next step)
   → If no reviewer CLI found (codex / claude / qwen-code) → STOP with diagnostics
5. /polisade:implement: STOP
   /polisade:continue: NEXT TASK → Continue to next ready task
```

**⛔ CRITICAL: Status `done` is ONLY set after PR merge!**

| Step | Task Status |
|------|-------------|
| After code written | `in_progress` |
| After PR created | `review` |
| After PR merged | `done` |

**Do NOT skip steps. Do NOT set `done` early. Complete the FULL cycle for each TASK.**

**Stop for:**
- `waiting_pm` (PM decision needed)
- `blocked` (unresolvable technical issue)
- `/polisade:implement`: after merge of ONE task (STOP)
- `/polisade:continue`: all tasks done

**Auto-fix (don't stop for):** Failing tests, review comments, merge conflicts.

## Subagents Architecture

Commands `/polisade:spec`, `/polisade:roadmap`, `/polisade:tasks`, `/polisade:implement` launch isolated subagents with clean context.

| Command | System Role | Purpose |
|---------|-------------|---------|
| `/polisade:spec` | Technical Specification Architect | Create SPEC from PRD/FEAT |
| `/polisade:design` | Solution Design Architect | Create doc-as-code design package (C4/ERD/OpenAPI/ADR/glossary) from PRD or SPEC |
| `/polisade:roadmap` | Product Delivery Roadmap Architect | Create PLAN from SPEC |
| `/polisade:tasks` | Roadmap Item Planner | Create TASKs from PLAN/SPEC/FEAT/BUG/DEBT/CHORE |
| `/polisade:implement` | Developer | Implement code from TASK |
| `/polisade:review-pr` | Independent Quality Reviewer (external CLI or `self`) | Review PR vs TASK, score & improve |
| `/polisade:review` | Second Opinion Reviewer (external CLI or `self`) | Advisory review of TASK quality |

**Quality Review Loop:** After PR creation, reviewer (Codex CLI by default, or current agent's CLI with `self` flag) independently reviews the output against source requirements. Score >= 8 passes; score < 8 triggers improvement + re-review (max 2 iterations). If reviewer CLI is not available → STOP with diagnostics and installation instructions.

Knowledge flows between subagents via `.state/knowledge.json`.

## Artifact Types

| Type | Purpose | When to Create |
|------|---------|----------------|
| **PRD** | Full requirements for large initiative | New module, epic |
| **FEAT** | Feature Brief | Regular feature |
| **SPEC** | Technical specification | Complex feature requiring design |
| **DESIGN-PKG** | Doc-as-code design package (C4, ERD, OpenAPI, ADR, glossary) | Architectural artifacts for new modules / handoff between teams |
| **PLAN** | Implementation plan with phases | Large work with dependencies |
| **TASK** | Atomic task | Always — this is the work unit |
| **BUG** | Defect description | Bugs (auto-creates TASK) |
| **DEBT** | Technical debt | Refactoring (optionally creates TASK via `--task`) |
| **CHORE** | Simple task | Config, cleanup (creates TASK by default; `--no-task` to opt out) |
| **SPIKE** | Research task | Technology choice, PoC |
| **ADR** | Architecture Decision Record | Architectural decisions |

## Requirement ID Scoping

FR/NFR идентификаторы **локально уникальны** в пределах своего источника (PRD, SPEC или FEAT), но **не глобально**. В проекте может быть несколько top-level requirement documents (PRD + несколько FEAT по версиям + несколько SPEC), и один и тот же номер — `FR-007` — может быть объявлен в каждом из них как разное требование.

### Формат ссылок

- **Composite (обязателен для cross-doc refs)**: `{DOC_ID}.FR-NNN` / `{DOC_ID}.NFR-NNN`.
  Примеры: `PRD-001.FR-007`, `FEAT-002.FR-007`, `SPEC-002.NFR-003`.
  Номер всегда 3-значный (`FR-007`, не `FR-7` и не `FR-07`). DOC_ID ∈ {PRD-NNN, SPEC-NNN, FEAT-NNN}.
- **Bare `FR-NNN`** разрешён только как id-объявление внутри самого документа-источника (`### FR-007 — …` в SPEC), либо как implicit scope «требование из parent документа текущего артефакта» — и только если в проекте **ровно один** top-level doc объявляет это FR.

### Где используется composite

- `tasks/TASK-*.md` → `requirements: [SPEC-001.FR-001, SPEC-001.NFR-002]`
- `docs/architecture/decisions/ADR-*.md` → `addresses: [SPEC-001.FR-001]`
- `docs/architecture/DESIGN-*/manifest.yaml` → `artifacts[].realizes_requirements: [SPEC-001.FR-001]`
- `docs/architecture/DESIGN-*/<sub-artifact>.md` frontmatter → `realizes_requirements: [...]`

### Резолюция bare ссылок (implicit scope)

Если в frontmatter написан bare `FR-007`, plugin резолвит его по цепочке parent-документа:

- `TASK` → `parent` (PLAN или SPEC/PRD/FEAT/BUG/DEBT/CHORE). Если `parent: PLAN-XXX` — через `PLAN.parent` (канонически `SPEC-XXX`).
- `ADR` → первый элемент `related: [...]` с префиксом PRD-/SPEC-/FEAT-.
- `DESIGN` sub-artifact → `manifest.parent` пакета-контейнера.

### ⛔ Guard-rule для LLM: НЕ делай `grep -r FR-NNN`

Когда PM говорит «удали FR-07 из такого-то документа и все ссылки на него»:

1. **Сначала уточни, в каком документе** объявлено удаляемое FR.
2. **Не** делай `grep -r 'FR-07' .` по всему проекту и **не** предлагай удалить совпадения в других документах без явного согласия PM.
3. `FR-07` в `PRD-001` и `FR-07` в `FEAT-002` — это **разные требования**. Удаление одного не должно трогать другое.
4. Если в проекте используется composite (`PRD-001.FR-007`), для удаления pattern однозначен — можно спокойно grep'ить по полному id. Если же в проекте ещё встречается bare `FR-07` — сначала запусти `/polisade:migrate --apply` (проставит scope-prefix для ambiguous), и только потом удаляй.

### Поддерживающие инструменты

- **`/polisade:migrate --apply`** — канонизирует legacy 2-digit (`FR-07` → `FR-007`) и проставляет composite prefix для bare коллидирующих refs в существующем проекте. Идемпотентен.
- **`/polisade:doctor --traceability`** — показывает матрицу по каждому top-level doc отдельно (`PRD-001.FR-007` vs `FEAT-002.FR-007`) и warning-секцию про ambiguous bare refs (non-blocking).
- **`polisade_lint_artifacts.py`** — блокирует коммит (exit=1) при cross-doc bare reference на коллидирующий id.

## Status Machine

Polisade Orchestrator artifacts have **two distinct lifecycles** depending on type:

### Top-level requirement artifacts (PRD / SPEC / FEAT / DESIGN-PKG)

These are **living documents** (per ISO/IEC/IEEE 29148 §5.2.1) — they describe WHAT, not WHEN. They never become `done`; they get baselined and stay active as long as their downstream work runs.

```
draft → reviewed → ready → accepted
                     ↓
                  blocked / waiting_pm
```

- `draft` — being written
- `reviewed` — passed self-review (SPEC subagent score ≥ 8)
- `ready` — PM approved, downstream work (PLAN/TASK/DESIGN) may start
- `accepted` — baselined; multiple children created or implementation underway. Long-lived state.

⛔ Creating a child (PLAN, TASK, DESIGN-PKG) **does NOT close the parent.** SPEC/PRD/FEAT stay `ready`/`accepted` for the entire lifetime of their downstream work.

### Work-unit artifacts (TASK / BUG / DEBT / CHORE / SPIKE)

These are **closeable units of work** — they describe a single change that gets merged.

```
draft → ready → in_progress → review → done
              ↓           ↓       ↓
           blocked    waiting_pm  changes_requested
                                        ↓
                                  in_progress
```

`done` is **only** valid for work-unit artifacts and **only after PR merge**.

### ADRs

```
proposed → accepted → deprecated / superseded
```

## Project Structure

```
docs/
├── prd/             # PRD-001-name.md
├── specs/           # SPEC-001-name.md
├── plans/           # PLAN-001-name.md
├── architecture/    # design + decision corpus
│   ├── DESIGN-001-name/  # design packages from /polisade:design
│   ├── decisions/        # ADR-001-name.md (Architecture Decision Records)
│   └── runs/             # ARCHRUN-001.md (corpus-run logs, experimental)
├── conventions/     # ПРАВИЛА ЭТОЙ КОМАНДЫ (см. ниже) — README.md каркас
└── templates/       # Document templates

backlog/
├── features/   # FEAT-001-name.md
├── bugs/       # BUG-001-name.md
├── tech-debt/  # DEBT-001-name.md
├── chores/     # CHORE-001-name.md
└── spikes/     # SPIKE-001-name.md

tasks/          # TASK-001-name.md  ⛔ ТОЛЬКО корневая `tasks/` — НЕ `docs/tasks/`!

.state/
├── PROJECT_STATE.json  # Central state file (CRITICAL)
├── counters.json       # ID counters
├── knowledge.json      # LLM memory between sessions
└── session-log.md      # Session log (audit trail)
```

## Временные файлы

Polisade-скиллы пишут промежуточные артефакты (PR body, diff-снэпшоты, отчёты)
в `.polisade/tmp/` — project-local и в `.gitignore`. Туда же попадает
`pr-body-<TASK-ID>.md` от `/polisade:implement`.

`/tmp` НЕ используется: GigaCode CLI изолирует его через виртуальную FS
(`~/.gigacode/tmp/<hash>/`), и файлы, записанные одним tool-call'ом,
становятся невидимы последующим Read/ReadFile. Если пишешь свой скрипт
или скилл — клади промежуточные файлы в `.polisade/tmp/`, не в `/tmp/`
(issue #57 / legacy OPS-009; подробнее — `docs/gigacode-cli-notes.md` §4).

## Critical State Files

### `.state/PROJECT_STATE.json`
Central state file. After EVERY operation that changes artifacts:
1. Read current state
2. Update relevant fields
3. Write back

Contains: `polisadeVersion`, `schemaVersion`, `project`, `settings.gitBranching`, `settings.reviewer.{mode,cli}`, `settings.workspaceMode`, `settings.vcsProvider`, `settings.debt.autoCreateTask`, `settings.chore.autoCreateTask`, `artifacts`, `waitingForPM`, `blocked`, `readyToWork`, `inProgress`, `inReview`.

### `.state/knowledge.json`
LLM memory between sessions:
- `projectContext`: name, techStack, keyFiles, entryPoints
- `patterns`: patterns to follow
- `antiPatterns`: patterns to avoid
- `decisions`: architectural decisions (links to ADRs)
- `testing.strategy`: test authoring strategy — `"tdd-first"` (default) or `"test-along"`
- `learnings`: lessons from implementation
- `conventions`: `{path, files}` — где лежат правила команды и какие файлы там
  найдены. Список собирает `/polisade:sync --apply` механически, не читая
  содержимое (см. ниже)

## Правила команды — `docs/conventions/`

Архитектурные принципы, стиль кода, дисциплина тестов, требования
безопасности и работа со стендами живут в `docs/conventions/*.md` — это
**правила ЭТОГО проекта**, их пишет команда, а не плагин. Оркестратор
намеренно не знает ни языка, ни архитектуры: захардкоженные «интерфейсы и
SOLID» бессмысленны для половины стеков.

- Пиши правила в тематические файлы рядом с `docs/conventions/README.md`
  (сам README — каркас и в список не попадает).
- После правок — `/polisade:sync --apply`: он перечислит файлы в
  `.state/knowledge.json → conventions.files`. **Содержимое не читается и
  не пересказывается**, ручные правки не перезатираются.
- Перед коммитом исполнитель проверяет пункт `Project conventions applied`,
  ревьюер в `/polisade:review-pr` читает файлы из `conventions.files` и
  цитирует применённые правила. Список пуст → честное `N/A`, а не молчание.

### `.state/counters.json`
ID counters for all artifact types. Increment after creating each artifact.

## Git Worktree Strategy

Check `settings.workspaceMode` and `settings.gitBranching` in PROJECT_STATE.json.

### If workspaceMode: "worktree" AND gitBranching: true

Each task gets its own git worktree — isolated working directory.

**Location:** `.worktrees/{branch__name}/` (inside project root, in `.gitignore`)
**State:** Each worktree has its own `.state/` copy (NO concurrent writes)
**Counters:** `counters.json` stays in main repo only (NO copies)

**Branch naming (unchanged):**
- `feat/FEAT-XXX-slug` → folder `feat__FEAT-XXX-slug`
- `fix/BUG-XXX-slug` → folder `fix__BUG-XXX-slug`
- `plan/PLAN-XXX-TASK-YYY-slug` → folder `plan__PLAN-XXX-TASK-YYY-slug`

### Parallel Work

```
Terminal 1: /polisade:implement TASK-001  → .worktrees/feat__FEAT-001-auth/
Terminal 2: /polisade:implement TASK-005  → .worktrees/plan__PLAN-001-TASK-005-api/
Terminal 3: /polisade:implement TASK-008  → .worktrees/fix__BUG-003-crash/
```

Always specify TASK-ID explicitly for parallel work!

### After Parallel Work
1. Each agent merges its PR independently
2. In main repo: `git pull origin main`
3. Run `/polisade:sync --apply` — reconciles state from merged .md files
4. Cleanup: `git worktree list` → `git worktree remove <path> --force`

### Status Updates
When changing TASK status, ALWAYS update BOTH:
- `.state/PROJECT_STATE.json` (local copy in worktree)
- TASK `.md` file frontmatter (committed, source of truth for `/polisade:sync`)

### If workspaceMode: "inplace" (legacy)
Uses `git checkout -b` instead of worktree. Not safe for parallel work.

### Commit Format
```
[TASK-ID] brief description
```

## Priority Order for `/polisade:continue`

1. `changes_requested` — fix review comments
2. `in_progress` — finish started work
3. `ready` TASK from BUG (P0 > P1 > P2)
4. `ready` TASK
5. `ready` TASK from CHORE
6. `ready` TASK from DEBT (P0-P1)
7. `ready` SPIKE
8. `ready` PLAN → `/polisade:tasks`
9. `ready` SPEC → `/polisade:tasks`
10. `ready` FEAT → `/polisade:tasks`
11. `ready` PRD → `/polisade:spec`
12. `ready` TASK from DEBT (P2+)

## PM Checkpoints (When to Stop and Ask)

- FEAT size M/L → ask if spec needed
- Creating > 3 TASKs → show plan, wait for confirmation
- Architectural choice → offer options with recommendation
- First PR in session → notify PM for review

## Git Safety

- ⛔ NEVER `git add -f <path>` / `git add --force <path>` на любой путь,
  который игнорируется `.gitignore`. Принудительное добавление обходит
  `.gitignore` и может закоммитить служебные файлы CLI против желания
  пользователя. Разрешено только если PM явно попросил «добавить
  принудительно» в этой же реплике.
- ⛔ NEVER `git add .gigacode/` / `git add .qwen/` / `git add .codex/` /
  `git add .worktrees/` — это служебные директории CLI-плагинов. В
  `/polisade:init`-сконфигурированном проекте они в `.gitignore`
  (см. append-блок в `skills/init/SKILL.md` шаг 5).<!-- polisade:claude-only BEGIN --> Исключение —
  **файл** `.claude/settings.json` (НЕ директория `.claude/` целиком):
  это permission-allowlist для Claude Code plugin'а, его коммитят
  целенаправленно.<!-- polisade:claude-only END -->
- ⛔ NEVER модифицировать `.gitignore` ради того, чтобы «починить»
  untracked служебную директорию.

**Как парсить «закоммить всё, КРОМЕ X»**: это явное ИСКЛЮЧЕНИЕ, не
фокус. Не форсить X, не трогать `.gitignore` ради X, не переносить X в
tracked. При сомнении — переспросить PM.

**Untracked в `git status`**: если видишь `.gigacode/` / `.qwen/` /
`.codex/` / `.worktrees/` в untracked — это НОРМА, они попадают в
`.gitignore` после `/polisade:init`. Не «помогай» добавлением. Про
`.venv/` / `node_modules/` / `vendor/` / `target/` и прочие stack-specific
пути: в template `.gitignore` они **закомментированы** — каждый проект
раскомментирует нужные под свой стек. Если видишь такой путь в
untracked и он должен быть игнорирован — попроси PM раскомментировать
соответствующую строку в `.gitignore`, **не** предлагай `git add -f`.

<!-- polisade:claude-only BEGIN -->
**Исключения для `.claude/`**: коммитится только `.claude/settings.json`
(создаётся `/polisade:init`, см. `skills/init/SKILL.md:86`,
`README.md:106`). Прочее содержимое `.claude/` (локальные логи, cache,
planning-заметки в `.claude/plans/`) — **НЕ** коммитить, даже если PM
говорит «добавь всю папку `.claude`». Используй `git add .claude/settings.json`
поштучно, не `git add .claude/`.
<!-- polisade:claude-only END -->

## Self-Review Gate (Required Before Commit)

**⛔ MUST OUTPUT CHECKLIST before commit!**

Subagent MUST before committing:
1. **Use Read tool** — re-read ALL changed files
2. **OUTPUT checklist** in this format:

```
───────────────────────────────────────────
SELF-REVIEW CHECKLIST
───────────────────────────────────────────
[✓] Hardcoded / stand-dependent values: no passwords/keys AND no
    stand-dependent literals (DB schema name, stand/environment name,
    namespace, hostname/port, absolute local path) — those go through
    config/profile/env, never as a literal in a class
[✓] Error handling: errors handled per stack conventions
[✓] Patterns: follows patterns from knowledge.json
[✓] Anti-patterns: no violations
[✓] Project conventions (docs/conventions/*.md) applied — cite the rules you
    followed; N/A if conventions.files is empty
[✓] Tests: tests added/updated
[✓] Tests quality: no sleep/random/order dependency, no assertion-free
    tests, tests check behaviour rather than structure
[✓] HTTP rubric applied: every request classified against the contract; no
    FAIL re-labelled as ⚠️ (N/A for a diff without handlers/controllers/routes)
[✓] Schema changes only via migration tool: DDL goes through the migration
    tool. A direct change to a live DB happened only with a filled «Schema
    fix decision» block AND a new migration file in the same commit — the
    block alone does not legalize it
[✓] TDD: tests written before code (if testing.strategy: "tdd-first"; N/A if "test-along")
[✓] Acceptance criteria: all met
───────────────────────────────────────────
Ready to commit: YES
```

3. If any [✗] — **FIX and repeat checklist**
4. Only after all [✓] — commit

**⚠️ COMMIT WITHOUT EXPLICIT CHECKLIST OUTPUT = PROTOCOL VIOLATION!**

**No stand-dependent values in code (issue #161).** Secrets are not the only
thing that must stay out of the source. A value that DIFFERS between local /
test-stand / prod — DB schema name, stand or namespace name, hostname, port,
absolute local path — is stand-dependent configuration, not code. Hardcoding
it passes a secrets-only checklist and then fails on another stand, where the
literal still «looks correct» and is expensive to find. Externalize it:
`application-{profile}.yml`, `.env`, or an environment variable.

**HTTP response rubric (issue #87).** When you make HTTP calls yourself
(curl / httpx / RestAssured / Playwright API), first write the table of
requests — `method | path | input | status | body`, one row per raw call —
then classify. `2xx` with a contract-shaped body = PASS. `4xx` = PASS **only**
when that exact status is documented (OpenAPI `responses`, an AC, SPEC §7) and
you cite where; otherwise FAIL. `5xx` = FAIL, with exactly one
exception you must produce: the status is described in the contract's `5xx`
response section and you cite it. "The server answered" and "my script
survived" are not that exception. Any other class
(`1xx`, `3xx`, or a `2xx` whose body is not the promised one) follows the
`4xx` rule: PASS only against a cited contract, otherwise FAIL. Timeout /
connection refused = FAIL (infrastructure). No row may stay unclassified.
With no contract in any of those places you may **not**
label a 4xx/5xx as expected: stop and ask the PM to fix the contract. If any
row is FAIL, the summary cannot say «everything works» or carry a 🎉 — a
«Failing requests» section with the raw output is mandatory.

**Schema fix discipline (issue #88).** Drift between an ORM entity and the
live database is fixed in one direction: SSOT (`data-model.md` or the
migration files) → migration → code. DDL goes through the migration tool
(Liquibase / Flyway / Alembic / Prisma / Django / goose). A direct
`ALTER`/`CREATE`/`DROP` via psql/JDBC, `ddl-auto=update` or `prisma db push`
against a live DB is not reproducible on another stand — it must be paused and
recorded as a «Schema fix decision» block in the TASK file (Symptom, Drift,
SSOT, Root cause, Fix side, Reproducibility). Once DDL has been run against a
live DB, `Fix side` is `migration` by definition: the change must land in a new
migration file in the same commit, or it does not exist anywhere else.

## Validation Rules

| Command | Accepts | Creates |
|---------|---------|---------|
| `/polisade:spec` | PRD or FEAT with status `ready` | SPEC |
| `/polisade:design` | PRD or SPEC with status `ready` | DESIGN-PKG (+ optional ADRs) |
| `/polisade:roadmap` | SPEC with status `ready` | PLAN |
| `/polisade:tasks` | PLAN, SPEC, FEAT, BUG, DEBT, or CHORE with status `ready` | TASK[] |
| `/polisade:implement` | **ONLY TASK** with status `ready` | Code |

## System Boundary

When implementing TASKs, the agent works **ONLY** within the system specified
in `system_boundary` of the parent SPEC frontmatter (if set).

### Rules

1. **Code is created only for our system** — not for external systems listed in `external_systems`
2. **Integrations are implemented as clients/adapters** — we write an HTTP client to the external API,
   not the external system itself
3. **Consumed contracts are read-only** — files in `docs/contracts/consumed/` are never modified
4. **Provided contracts** — files in `docs/contracts/provided/` — are modified
   only through `/polisade:design` or with explicit intent
5. **Integration tests** — use mocks/stubs/WireMock for external systems;
   this is test infrastructure, not production code of the external system
6. **If a TASK requires changes in an external system** — the agent creates an Open Question,
   not the change itself

These rules apply when the parent SPEC has a non-empty `external_systems` list.
If no SPEC or no `external_systems` — section is informational only.

## Status Output Format

```
═══════════════════════════════════════════
  PROJECT STATUS
═══════════════════════════════════════════

READY TO WORK (N):
   • TASK-001 → /polisade:implement
   • SPIKE-001 → research

WAITING FOR PM (N):
   • TASK-003: "question"

BLOCKED (N):
   • TASK-005: reason

IN PROGRESS (N):
   • TASK-002: what's being done

IN REVIEW (N):
   • PR #123: FEAT-001

ARCHITECTURE:
   • Active ADRs: 5

RECOMMENDATION:
   → Specific action
```

## When to Work Autonomously

- Artifacts with status `ready` exist
- Task is clear and doesn't need clarification
- No technical blockers

## When to Stop and Ask PM

- Business decision required (priority, scope, trade-off)
- External information needed (API keys, credentials, access)
- Architectural choice with significant consequences
- Task contradicts existing requirements
- Creating > 3 TASKs
- FEAT size M or L

## Python-интерпретатор

Любой python-скрипт (`scripts/polisade_drift_gate.py`, скрипты плагина)
запускается через токен `${POLISADE_PYTHON:-python3}`. Дефолт `python3`
покрывает macOS/Linux; на Windows `python3` обычно не на PATH (штатный
инсталлятор ставит `python.exe` и лаунчер `py`), поэтому машина один раз
выставляет `POLISADE_PYTHON`.

<!-- polisade:python-stop CAPSULE BEGIN -->
> ⛔ **Интерпретатор не стартовал — STOP, а не поиск.** Python-скрипты плагина зовутся ТОЛЬКО как `${POLISADE_PYTHON:-python3} …`. Если упал сам вызов, ещё до скрипта (`command not found`, `не является внутренней или внешней командой`, `No such file or directory`) — **не ищи интерпретатор по машине**: ни `where`/`which`, ни обход `C:\Python*`, ни `py -3` наугад, ни чужой venv. Найденный так путь недетерминирован — в следующий раз он будет другим.
> Процитируй ошибку дословно и попроси PM выставить `POLISADE_PYTHON`: команда на PATH (`py`, `py -3`, `python`) или абсолютный путь **без пробелов**. Подстановка голая, как у `POLISADE_PLUGIN_ROOT`: несколько слов разойдутся в argv — для лаунчера это верно, а путь с пробелами так разорвётся и не найдётся (на такой машине нужен шим на PATH). До ответа PM шаг не продолжается.
<!-- polisade:python-stop CAPSULE END -->

## Drift Gate (arch ↔ code, deterministic)

`scripts/polisade_drift_gate.py` — детерминированная сверка design-артефактов
с кодом (issue #205): OpenAPI paths/methods из `DESIGN-*/api.md` ↔ маршруты в
коде; Mermaid ER из `DESIGN-*/data-model.md` ↔ схема БД. Конфиг:
`docs/architecture/drift-gate.json`. Гейт **blocking** в CI
(`.github/workflows/polisade-drift-gate.yml`) и запускается на шаге
REGRESSION TEST перед PR.

Правила:
- Exit≠0 = дрейф. Устрани до PR: приведи код в соответствие design-артефактам
  **или** обнови design-артефакт в том же PR (DESIGN-DEVIATION протокол).
- ⛔ Агентского обхода НЕТ. Флаг `design_waiver` гейт не читает.
- Временный пропуск дрейфа — **только** ревьюируемый артефакт
  `docs/waivers/DRIFT-WAIVER-NNN.md` (шаблон:
  `docs/templates/drift-waiver-template.md`) с обоснованием и сроком
  `expires`. Его создаёт и утверждает PM; агент waiver НЕ создаёт.

## ADR (Architecture Decision Records)

Create ADR when:
- Choosing technology (DB, framework)
- Architectural pattern choice
- Deviation from SPEC

ADR statuses: `proposed` → `accepted` → `deprecated`/`superseded`

## VCS providers

Все операции над PR (create / view / list / diff / merge / comment / close) проходят через единую абстракцию `scripts/polisade_vcs.py`. Провайдер выбирается из `.state/PROJECT_STATE.json → settings.vcsProvider`:

- `github` (дефолт) — через `gh` CLI, обычный GitHub/GitHub Enterprise.
- `bitbucket-server` — self-hosted Atlassian Bitbucket Server через REST API.

### Bitbucket Server: настройка

1. Установи `settings.vcsProvider` в `"bitbucket-server"` (автоматически при `/polisade:init`, вручную + `/polisade:migrate --apply` для существующих проектов).
2. `/polisade:migrate --apply` создаёт `.env.example` (reference) и `.env` (stub), `.env` добавляется в `.gitignore` (некомментированной строкой). ⚠️ Под GigaCode Filesystem Guard скрипт миграции может быть недоступен (read-protected install-dir, #127) — тогда `.env` автоматически НЕ создаётся; создай его вручную: `cp .env.example .env`.
3. Заполни в `.env` хотя бы один домен:
   - `BITBUCKET_DOMAIN1_URL` + `BITBUCKET_DOMAIN1_TOKEN` (HTTP Access Token).
   - Опционально `BITBUCKET_DOMAIN2_URL` + `_TOKEN` для второго корпоративного Bitbucket.
   - `BITBUCKET_DOMAIN*_AUTH_TYPE=bearer` (дефолт) или `basic` при 401.
4. Инстанс выбирается автоматически по хосту `git remote get-url origin` — подходящий `BITBUCKET_DOMAIN{N}_URL` определяет, куда идти за PR.
5. Проверь конфигурацию:
   - `/polisade:pr whoami` — валидность токена и выбор инстанса.
   - `/polisade:doctor` — полная диагностика (`.env`, токены, origin-host match).

### Ручные операции над PR

Используй `/polisade:pr <sub>`:
- `/polisade:pr list [--head BRANCH]` — список открытых PR.
- `/polisade:pr view <id>` — метаданные PR.
- `/polisade:pr diff <id>` — полный diff.
- `/polisade:pr merge <id> [--squash] [--delete-branch]` — merge и удаление source-ветки.
- `/polisade:pr comment <id> --body "..."` — добавить комментарий.
- `/polisade:pr close <id>` — закрыть (GitHub: `CLOSED`, Bitbucket: `DECLINED`).

Для длинных тел комментариев — вызывай скрипт напрямую с `--body-file` или `--body-stdin` вместо `/polisade:pr comment --body "..."`, чтобы не страдать от shell-escape.

## Templates

Use templates from `docs/templates/` when creating documents:
- Always fill `status:` in frontmatter
- Always specify `id:` for tracking
- Link documents via `parent:` and `children:`
- For BUG specify `task:` with linked TASK; for DEBT/CHORE specify `task:` only when a linked TASK exists (DEBT: opt-in via `--task`; CHORE: default, opt-out via `--no-task`)