# Волна 1 — счётчик NO-GO наставника (inline, sealed-plan проба)

> **For agentic workers:** REQUIRED SUB-SKILL: inline-исполнение (субагенты `op:Task` запрещены машиной). Шаги — checkbox.

**Goal:** Собрать `mentor-nogo-counter.mjs` (счётчик NO-GO наставника, зеркало `bumpJudgeNoGo`) inline по запечатанному плану — и тем самым проверить, что цепь «якорная спека → печать → план → печать → стена открылась» реально работает на живом судье.

**Architecture:** Чистый модуль + тест, без правок существующих файлов. Это Волна 1 из серии; остальные модули фичи (карточка арбитража, парсер «Переговоры», форматтеры, эскалации) — отдельными волнами после проверки цепи.

**Tech Stack:** Node ESM, vitest tools-only (`npx vitest run --root app --config vitest.config.tools.mjs`).

**Опора на спеку (артефакт):** `2026-06-12-router-mentor-two-level-negotiation-design-v2.md`, якоря `{#testing}`, `{#components}`.

**Честная оговорка о хрупкости:** стена матчит каждое мутирующее действие со следующим шагом по порядку, точным совпадением. Любое отклонение (правка теста, лишний прогон) = действие вне плана → блок → пере-печать этой волны. Прогон vitest (проверка) делаю как наблюдение между шагами; если стена его не пустит — добавлю отдельным шагом и пере-печатаю.

```steps-json
[
  {"op":"Write","object":"tools/mentor-nogo-counter.test.mjs","ref":"testing"},
  {"op":"Write","object":"tools/mentor-nogo-counter.mjs","ref":"components"},
  {"op":"Bash","object":"git add tools/mentor-nogo-counter.mjs tools/mentor-nogo-counter.test.mjs && git commit -m wave1-mentor-counter","ref":"components"}
]
```

---

## Шаги

### Шаг 1 — Write `tools/mentor-nogo-counter.test.mjs` (падающий тест)

```js
import { describe, it, expect } from 'vitest';
import { bumpMentorNoGo, MENTOR_ESCALATE_AFTER } from './mentor-nogo-counter.mjs';

describe('bumpMentorNoGo', () => {
  const mem = () => {
    const store = {};
    return {
      readFileSync: (p) => { if (!(p in store)) { const e = new Error('no'); e.code = 'ENOENT'; throw e; } return store[p]; },
      writeFileSync: (p, d) => { store[p] = d; },
      mkdirSync: () => {},
    };
  };
  it('инкремент на blocked, сброс на allow', () => {
    const fsImpl = mem(); const dir = '/r'; const sessionId = 's1';
    expect(bumpMentorNoGo({ sessionId, blocked: true, fsImpl, dir })).toBe(1);
    expect(bumpMentorNoGo({ sessionId, blocked: true, fsImpl, dir })).toBe(2);
    expect(bumpMentorNoGo({ sessionId, blocked: false, fsImpl, dir })).toBe(0);
    expect(bumpMentorNoGo({ sessionId, blocked: true, fsImpl, dir })).toBe(1);
  });
  it('порог эскалации = 3', () => { expect(MENTOR_ESCALATE_AFTER).toBe(3); });
  it('небезопасный sessionId санитизируется (не падает)', () => {
    const fsImpl = mem();
    expect(bumpMentorNoGo({ sessionId: '../../x', blocked: true, fsImpl, dir: '/r' })).toBe(1);
  });
});
```

### Шаг 2 — Write `tools/mentor-nogo-counter.mjs` (реализация, зеркало `bumpJudgeNoGo`)

```js
#!/usr/bin/env node
/**
 * mentor-nogo-counter — счётчик подряд идущих NO-GO наставника (L1), зеркало
 * bumpJudgeNoGo. blocked=true → +1; allow → сброс 0. Порог 3 → арбитраж (round-control C-12).
 */
import fsDefault from 'node:fs';
import { join } from 'node:path';
import { runtimeDir } from './enforce-hook-helpers.mjs';

export const MENTOR_ESCALATE_AFTER = 3;

export function bumpMentorNoGo({ sessionId, blocked, fsImpl = fsDefault, dir = runtimeDir() } = {}) {
  const safe = String(sessionId || 'unknown').replace(/[^a-zA-Z0-9_-]/g, '_');
  const path = join(dir, `mentor-nogo-${safe}.json`);
  let count = 0;
  try { count = (JSON.parse(fsImpl.readFileSync(path, 'utf8')).count) || 0; } catch { count = 0; }
  const next = blocked ? count + 1 : 0;
  try { fsImpl.mkdirSync(dir, { recursive: true }); fsImpl.writeFileSync(path, JSON.stringify({ count: next })); } catch { /* best-effort */ }
  return next;
}
```

Между шагами 2 и 3 — прогон проверки (наблюдение): `npx vitest run --root app --config vitest.config.tools.mjs tools/mentor-nogo-counter.test.mjs` (ожидаю PASS).

### Шаг 3 — Bash коммит волны

`git add tools/mentor-nogo-counter.mjs tools/mentor-nogo-counter.test.mjs && git commit -m wave1-mentor-counter`
