feat(registry): фундамент-словарь capability-токенов (этап 2a, роутер-реестр)

Phase 2a эпика «роутер-реестр» (спека v2 §3, OPEN-1): расширен
docs/registry/capability-vocabulary.json 10 -> 26 токенов.

- A8-цепочка (10) сохранена.
- 9 токенов-мостов рабочих цепочек (создают рёбра графа producer<->consumer):
  feature-spec, implementation-plan, completed-change, code-review-feedback,
  raw-research, ui-design, marketing-draft, content-framework, close-entries.
- 7 токенов-данностей задачи (-> initialInputs в 2c): feature-intent,
  feature-or-bugfix, bug-or-failure, ui-task, user-understanding-need,
  marketing-content-task, close-source-data.
- Тест формы на реальном файле (validateVocabulary ok + счётчик + ключевые токены).

Атомарные produce-токены ~144 контрактов добавляются в 2b (словарь живой).
Структурная разведка подтверждена графом проекта (graphify, правило 14):
coverage-machine не подключён к живому enforce-judge-gate (работа 2c),
два реестра (контрактный community 92 / узловой community 20).

Регрессия: 4367 passed, exit 0 (5 чужих node:test исключены).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-19 08:57:36 +03:00
parent 08ab516786
commit 9ad00cf96c
2 changed files with 52 additions and 11 deletions
+29 -11
View File
@@ -1,15 +1,33 @@
{
"version": "0.1.0",
"version": "0.2.0",
"tokens": [
{"token": "running-portal", "label": "работающий портал (DAST-цель)", "description": "Запущенный веб-портал как цель динамической проверки."},
{"token": "laravel-config", "label": "конфигурация Laravel", "description": "Конфиг приложения Laravel (заголовки, debug, права)."},
{"token": "pii-inventory-task", "label": "задача аудита ПДн", "description": "Запрос на аудит персональных данных по 152-ФЗ."},
{"token": "portal-pre-launch", "label": "портал перед публикацией", "description": "Портал на стадии подготовки к выходу в интернет."},
{"token": "dast-report", "label": "отчёт DAST", "description": "Результат динамической атаки на живой портал (инъекции/XSS/обход входа/IDOR)."},
{"token": "cve-exposure-scan", "label": "скан CVE/экспозиции", "description": "Результат проверки известных уязвимостей и небезопасной внешней экспозиции."},
{"token": "laravel-config-audit", "label": "аудит конфигурации Laravel", "description": "Результат проверки безопасности конфигурации Laravel."},
{"token": "pii-152fz-audit", "label": "аудит ПДн/152-ФЗ", "description": "Результат аудита персональных данных на соответствие 152-ФЗ."},
{"token": "stride-model", "label": "STRIDE-модель угроз", "description": "Карта attack surface и приоритеты защиты перед публикацией."},
{"token": "go-live-verdict", "label": "вердикт go-live", "description": "Сводный вердикт GO/NO-GO по безопасности перед публикацией."}
{"token": "running-portal", "category": "given", "label": "работающий портал (DAST-цель)", "description": "Запущенный веб-портал как цель динамической проверки."},
{"token": "laravel-config", "category": "given", "label": "конфигурация Laravel", "description": "Конфиг приложения Laravel (заголовки, debug, права)."},
{"token": "pii-inventory-task", "category": "given", "label": "задача аудита ПДн", "description": "Запрос на аудит персональных данных по 152-ФЗ."},
{"token": "portal-pre-launch", "category": "given", "label": "портал перед публикацией", "description": "Портал на стадии подготовки к выходу в интернет."},
{"token": "dast-report", "category": "produced", "label": "отчёт DAST", "description": "Результат динамической атаки на живой портал (инъекции/XSS/обход входа/IDOR)."},
{"token": "cve-exposure-scan", "category": "produced", "label": "скан CVE/экспозиции", "description": "Результат проверки известных уязвимостей и небезопасной внешней экспозиции."},
{"token": "laravel-config-audit", "category": "produced", "label": "аудит конфигурации Laravel", "description": "Результат проверки безопасности конфигурации Laravel."},
{"token": "pii-152fz-audit", "category": "produced", "label": "аудит ПДн/152-ФЗ", "description": "Результат аудита персональных данных на соответствие 152-ФЗ."},
{"token": "stride-model", "category": "produced", "label": "STRIDE-модель угроз", "description": "Карта attack surface и приоритеты защиты перед публикацией."},
{"token": "go-live-verdict", "category": "produced", "label": "вердикт go-live", "description": "Сводный вердикт GO/NO-GO по безопасности перед публикацией."},
{"token": "feature-spec", "category": "bridge", "label": "спека/требования фичи", "description": "Согласованный дизайн+требования или PRD до плана. Выход brainstorming / product-management:write-spec; вход writing-plans."},
{"token": "implementation-plan", "category": "bridge", "label": "план реализации", "description": "Пошаговый план bite-sized задач. Выход writing-plans; вход executing-plans / subagent-driven-development."},
{"token": "completed-change", "category": "bridge", "label": "завершённая правка", "description": "Готовое изменение кода до ревью/мержа. Выход test-driven-development; вход requesting-code-review / finishing-a-development-branch."},
{"token": "code-review-feedback", "category": "bridge", "label": "фидбэк код-ревью", "description": "Замечания ревью до внедрения правок. Выход requesting-code-review; вход receiving-code-review."},
{"token": "raw-research", "category": "bridge", "label": "сырой research", "description": "Интервью/опросы/тикеты/тесты до синтеза. Выход design-plugin:user-research; вход design-plugin:research-synthesis / product-management:synthesize-research."},
{"token": "ui-design", "category": "bridge", "label": "решение UI/UX", "description": "Доменное UI/UX-решение (компоненты/паттерны/a11y). Выход frontend-design; вход design-plugin:design-handoff."},
{"token": "marketing-draft", "category": "bridge", "label": "драфт маркетинг-контента", "description": "Черновик контента с форматированием. Выход marketing-plugin:draft-content; вход marketing-plugin:brand-review."},
{"token": "content-framework", "category": "bridge", "label": "фреймворк контента", "description": "Шаблоны/фреймворки контента под канал. Выход marketing-plugin:content-creation; вход marketing-plugin:draft-content."},
{"token": "close-entries", "category": "bridge", "label": "проводки close", "description": "Подготовленные проводки month-end (accruals/prepaid/depreciation). Выход finance-plugin:journal-entry-prep; вход finance-plugin:close-management."},
{"token": "feature-intent", "category": "given", "label": "идея фичи", "description": "Замысел фичи/компонента/изменения поведения до проработки. Вход brainstorming / product-management:write-spec."},
{"token": "feature-or-bugfix", "category": "given", "label": "фича или багфикс", "description": "Задача на реализацию до написания кода. Вход test-driven-development."},
{"token": "bug-or-failure", "category": "given", "label": "баг/падение", "description": "Баг, упавший тест или неожиданное поведение. Вход systematic-debugging."},
{"token": "ui-task", "category": "given", "label": "UI-задача", "description": "Задача по интерфейсу: компонент/паттерн/состояние/a11y-принцип. Вход frontend-design / UI-пула."},
{"token": "user-understanding-need", "category": "given", "label": "потребность понять пользователей", "description": "Запрос на исследование пользователей. Вход design-plugin:user-research."},
{"token": "marketing-content-task", "category": "given", "label": "маркетинг-контент-задача", "description": "Задача создания маркетингового контента под канал. Вход marketing-plugin:content-creation."},
{"token": "close-source-data", "category": "given", "label": "данные для close", "description": "Накопления/prepaid/амортизация для month-end. Вход finance-plugin:journal-entry-prep."}
]
}
+23
View File
@@ -1,6 +1,29 @@
import { describe, it, expect } from 'vitest';
import fs from 'node:fs';
import { validateVocabulary, loadVocabulary, unknownTokens } from './capability-vocabulary.mjs';
describe('capability-vocabulary.json — реальный файл словаря (этап 2a)', () => {
const raw = JSON.parse(fs.readFileSync('docs/registry/capability-vocabulary.json', 'utf8'));
const r = validateVocabulary(raw);
it('форма валидна → ok, без ошибок', () => {
expect(r.errors).toEqual([]);
expect(r.ok).toBe(true);
});
it('фундамент-набор присутствует (A8 + мосты + данности)', () => {
expect(r.tokens.size).toBe(26);
// A8-цепочка
for (const t of ['running-portal', 'dast-report', 'go-live-verdict']) expect(r.tokens.has(t)).toBe(true);
// мосты рабочих цепочек (создают рёбра графа)
for (const t of ['feature-spec', 'implementation-plan', 'completed-change', 'code-review-feedback', 'raw-research', 'ui-design', 'marketing-draft', 'content-framework', 'close-entries'])
expect(r.tokens.has(t)).toBe(true);
// данности задачи (→ initialInputs в 2c)
for (const t of ['feature-intent', 'feature-or-bugfix', 'bug-or-failure', 'ui-task'])
expect(r.tokens.has(t)).toBe(true);
});
});
describe('validateVocabulary — форма словаря', () => {
const good = { version: '0.1.0', tokens: [
{ token: 'dast-report', label: 'отчёт DAST', description: 'результат динамики' },