Схемы (формальные)¶
Назначение: машино-читаемые YAML frontmatter схемы для всех типов артефактов RENAR. Используются нативными для носителя валидаторами для проверки соответствия. Нормативные определения структуры — в
standard/06,standard/07,standard/08,standard/09. Валидация примеров:node scripts/validate-schema-examples.js. Этот документ — справочник (informative lookup).
1. Общий frontmatter (все артефакты требований и SPEC)¶
Поля, общие для BR/SR/TR/SPEC-* (канонические v1.0). Legacy типы UIC / AIC / INT-SR / TS deprecated в v1.0 (standard/04 §4.14.1).
# Identity
id: "<TYPE>-NN[.N]"
title: "<short, descriptive>"
type: BR | SR | TR | SPEC-ARCH | SPEC-API | SPEC-DATA | SPEC-INT | SPEC-PROC | SPEC-UI | SPEC-AI | SPEC-SEC | SPEC-OPS | SPEC-TEST | SPEC-DOC
slug: "<kebab-case>"
# Scope
level: system | subsystem | module
scope: { system: "<system-id>", subsystem: "<subsystem-id>" } # subsystem=null если level=system
# Жизненный цикл (verified — BR/SR; frozen — ADAPT §7; ready/passing/failing — TC §8; см. standard/04 §4.6)
status: draft | review | approved | verified | deprecated | obsolete | frozen
priority: must | should | could # MoSCoW; SAFe — через WSJF (BR-specific)
# Provenance (conditional, standard/07 §7.4.1): ADAPT реактивен.
# Findings present → source.adapt + adapt-section mandatory. No findings → adversarial-review-ref mandatory.
# source.tz-section — обязательно всегда.
source:
adapt: "ADAPT-NNN" # conditional
adapt-section: "Forward §N.N" # mandatory если adapt present
tz-section: "§N.N" # обязательно всегда
adversarial-review-ref: "AR-NNN" # mandatory когда adapt omitted → AR (standard/07 §7.4.6)
document-ref: "<ссылка>" # pinned ревизия source-документа
implementation-originated: {} # conditional; см. §1.1 (standard/06 §6.13)
# Hierarchy
parent: { id: "<parent-id>", ref: "<ссылка>" } # id required для SR (→BR), TR (→SR); optional для BR
children: [] # auto-derived
# Связь с SPEC (граф)
constrained-by: [] # SR → SPEC-* (типизированные рёбра)
implements-spec: [] # TR → SPEC-*
depends-on: [] # между SPEC
# Verification
verified-by: [] # auto-derived; TC IDs
verifies-business-goal: "" # optional
# AI provenance (RENAR-4+ обязательно для approved)
ai-provenance:
generated-by: "<vendor>-<model>@<date>"
prompt-template: "<template-path>@<version>"
context-tokens: integer
output-tokens: integer
generation-time-ms: integer
generated-at: "<ISO-8601>"
human-edits: boolean # true required для approved
# AI cost budget (optional)
ai-budget: { context-tokens-target: integer, context-tokens-actual: integer, output-tokens-target: integer, output-tokens-actual: integer, generation-time-target-ms: integer }
# Замена + schema versioning
replaces: "<old-id>"
replaced-by: "<new-id>"
deprecated-date: "<ISO date>"
schema-version: "1.0"
1.1 source: implementation-originated — требование, порождённое реализацией¶
Узкий легальный класс происхождения BR / SR / SPEC (standard/06 §6.13): внутренняя техническая деталь, добавленная при реализации (защитная проверка, внутренняя валидация, журналирование, обработка граничного случая). Наблюдаемое клиентом поведение этим классом покрывать запрещено — оно проходит только через контрактный контур (ADAPT / ACTZ с подписями).
source:
tz-section: "§N.N" # обязательно всегда (в том числе здесь)
implementation-originated:
change-unit-ref: "<ссылка на единицу изменения реализации>" # обязательно — провенанс
rationale: "<почему функциональность признана нужной>" # обязательно
human-approval: # обязательно; V6
approved-by: "<имя супервайзера-человека>"
role: "<роль>"
approved-at: "<ISO-datetime>"
observable-by-client: false # обязательно; true → несоответствие (standard/06 §6.13.4)
covering-tc: "TC-NN" # обязательно; TC существует и проходит до слияния
mutation-check: # обязательно — компенсация отсутствия красной истории
mutants-killed: integer # ≥ 1; иначе TC не является доказательством (standard/09 §9.18.2)
report-ref: "<ссылка на отчёт мутационной проверки>"
| Правило | Уровень |
|---|---|
Утверждение человека (human-approval) обязательно; агент не может легализовать собственную добавку |
normative |
covering-tc существует и проходит до включения изменения |
hook-enforced |
У covering-tc не может быть красной истории; вместо неё обязателен убитый мутант (mutation-check.mutants-killed ≥ 1) |
hook-enforced |
observable-by-client: true при implementation-originated — несоответствие (обязательство перед клиентом не возникает из кода) |
normative |
| Доля артефактов класса — счётчик в метриках дрейфа (standard/12 §12.3) | normative |
2. BR — Business Requirement¶
# Extends common §1, дополнительно:
level: system | subsystem # BR на уровне модуля запрещён (standard/06 §6.4)
scope: { system: "<system-id>", subsystem: "<subsystem-id>" }
# Межуровневая связь BR подсистемы → BR системы (standard/06 §6.8.2)
implements: # массив; substrate-agnostic ссылка
- { id: BR-NN, scope: { system: "<system-id>" }, rationale: "<short>" } # rationale опционально
implemented-by: [] # auto-derived (обратное ребро; не пишется автором)
business-context:
stakeholder: "<role>"
business-goal: "<short statement>"
kpi-impact:
- { kpi: "<name>", direction: increase|decrease, target: "<measurable>" }
# business-outcome — required для QG-4
business-outcome:
measurement-type: kpi | survey | observation | usage
kpi-name: "<KPI>"
measurement-method: "<how>"
baseline-value: number
baseline-measured-at: "<ISO date>"
target-value: number
target-met-by: "<ISO date>"
current-value: { value: number, measured-at: "<ISO date>", achievement: "<percent>" }
prioritization: { framework: WSJF|RICE|MoSCoW, wsjf-score: number, prioritized-at: "<ISO date>", prioritized-by: "<role>" }
data-classification:
contains-pii: boolean
contains-financial: boolean
contains-health: boolean
contains-children-data: boolean
retention-days: integer
data-residency: ["RU" | "EU" | "US" | ...]
compliance:
- { standard: "ISO 27001:2022", control: "<id>", rationale: "..." }
- { standard: "GDPR", article: "Art.NN" }
- { standard: "ФЗ-152", article: "ст.NN" }
ai-act: { risk-class: prohibited|high|limited|minimal, rationale: "<reason>", high-risk-domain: boolean }
Поля implements[] / implemented-by[] — нормативные правила¶
| Правило | Уровень |
|---|---|
implements[] обязателен при level: subsystem И когда родительская система имеет ≥1 approved BR |
recommended v1.0; обязательно v1.1+ |
Target BR обязан быть в статусе approved или выше на момент approve данного BR |
hook-enforced |
Cycle detection: цепочка implements не должна образовывать циклов |
hook-enforced |
implements[] — не parent-edge; запрет множественных parents (standard/06 §6.8.3) распространяется на SR/TR, не на BR |
normative |
Deprecate target BR → cascade-warning для всех implemented-by (не cascade-deprecate) |
hook-enforced |
Cross-substrate синтаксис: id + scope.system не зависит от носителя |
normative |
| Cardinality: array (0..N) | normative |
Гейт обеспечения соблюдения — scripts/check-implements-edge.js. Поле implemented-by — auto-derived; ручная запись запрещена.
3. SR — System Requirement¶
# Extends common §1, дополнительно:
parent:
id: "BR-NN" # required
# Источник ADAPT — через канонические source.adapt / source.adapt-section (§1).
# Отдельного поля derived-from-adapt нет (standard/06 §6.6.2).
constrained-by: # типизированные рёбра к SPEC-*
- "SPEC-UI-NN"
- "SPEC-API-NN"
- "SPEC-DATA-NN"
- "SPEC-SEC-NN"
quality-characteristic: # ISO/IEC 25010:2023 (9 характеристик; interaction-capability ← usability, flexibility ← portability в 25010:2011; safety — новая в 25010:2023)
- functional-suitability | performance-efficiency | compatibility | interaction-capability | reliability | security | maintainability | flexibility | safety
# Inherited from parent BR (если применимо): data-classification, compliance, ai-act
4. TR — Task Requirement¶
# Extends common §1, дополнительно:
parent:
id: "SR-NN" # required
implements-spec: [] # SPEC-* реализуемые этой задачей
estimated-effort: "<short statement>" # optional, free-form
5. SPEC-* common schema¶
Все 11 типов SPEC делят общую структуру (§1) + следующие SPEC-specific поля:
type: SPEC-ARCH | SPEC-API | SPEC-DATA | SPEC-INT | SPEC-PROC | SPEC-UI | SPEC-AI | SPEC-SEC | SPEC-OPS | SPEC-TEST | SPEC-DOC
referenced-by: [] # auto-derived
depends-on: [] # SPEC от которых этот зависит
compliance-refs: [] # ISO / GDPR / ФЗ-152 / AI Act / NIST AI RMF
Обязательные разделы body: ## Назначение, ## Scope, ## <Type-specific sections — см. §6>, ## Связь с требованиями, ## Связь с другими SPEC, ## Verification, ## Open questions.
6. SPEC type-specific extensions¶
Type-specific поля для 11 типов SPEC. Industry references — в standard/14. Legacy замены: UIC → SPEC-UI, AIC → SPEC-AI, INT-SR → SPEC-INT.
6.1 SPEC-ARCH, SPEC-API, SPEC-DATA, SPEC-INT, SPEC-PROC¶
# SPEC-ARCH
arch-style: monolith | microservices | modular-monolith | serverless | hybrid
deployment-model: cloud | on-prem | hybrid | edge
tech-stack: { languages: [], frameworks: [], data-stores: [], message-brokers: [] }
quality-attributes: [{ name: latency, target: "p95 < 200ms" }, { name: availability, target: "99.9%" }]
# SPEC-API
api-style: rest | graphql | grpc | websocket | async-events
api-version: "v1.2.0"
versioning-strategy: url-path | header | query-param | content-negotiation
authentication: bearer-jwt | api-key | oauth2 | mtls | none
rate-limits: [{ endpoint: "*", limit: "1000/min/key" }]
contract-file: { format: openapi-3.1 | asyncapi-2.6 | proto3, location: "contracts/<name>.yaml" }
# SPEC-DATA
data-style: relational | document | graph | columnar | hybrid
storage-engine: postgresql | mysql | couchdb | mongodb | clickhouse | ...
schema-version: "1.4.0"
pii-classification: [{ entity: User, fields: [email, phone], level: PII-high }]
retention-policies: [{ entity: Order, period: "7 years", basis: "tax law" }]
migration-strategy: forward-only | reversible | dual-write
# SPEC-INT
integration-pattern: request-response | event-driven | message-queue | webhook | file-transfer
direction: outbound | inbound | bidirectional
counterparty: { system: "<external-name>", contract-owner: "<team-or-vendor>", contract-ref: "<external-spec-url>" }
sla: { availability: "99.5%", latency-p95: "500ms", fallback: "queue + retry; manual reconciliation after 24h" }
idempotency: guaranteed | best-effort | none
# SPEC-PROC
process-style: bpmn | state-machine | saga | choreography | orchestration
state-count: integer
participants: [{ role: customer, system: client-portal }, { role: agent, system: back-office }]
sla: { end-to-end: "2 business hours" }
compensation: defined | not-applicable | manual
6.2 SPEC-UI, SPEC-AI, SPEC-SEC, SPEC-OPS¶
# SPEC-UI
ui-platform: web | mobile-ios | mobile-android | desktop | tv | embedded
target-users: [{ role: end-customer, persona: "ADAPT-NNN §X.Y" }]
design-system: "<reference-or-internal>"
accessibility-level: WCAG-A | WCAG-AA | WCAG-AAA
i18n: required | not-required
mockup-links: [{ tool: figma, url: "<link>", version: "v3" }]
baseline-images: ["ai-concepts/baselines/SPEC-UI-NN-screen-01.png"]
# SPEC-AI (judge-model.vendor ≠ production-model.vendor — нормативно)
ai-pattern: rag | fine-tuning | prompt-engineering | tool-use | multi-agent | embedding-only
production-model: { vendor: anthropic|openai|google|local, model: "<name>", version: "<exact>" }
judge-model: { vendor: "<different-vendor>", model: "<different-model>" }
context-strategy: { embedding-model: "<model>", chunk-size: integer, chunk-overlap: integer, vector-store: pinecone|weaviate|pgvector|qdrant }
eval-strategy: { metric: accuracy|f1|rouge|custom-rubric, threshold: number, baseline-dataset: "<path>" }
cost-budget: { tokens-per-request-target: integer, tokens-per-request-ceiling: integer, monthly-budget-usd: number }
# SPEC-SEC
security-domains: [authentication, authorization, data-protection, audit, secrets-management]
auth-model: { authn: jwt-bearer|oauth2-pkce|mtls|passkey, authz: rbac|abac|relbac }
data-classification: [{ class: PII-high, fields: [...] }, { class: PCI, fields: [...] }]
threat-model-method: STRIDE | PASTA | OCTAVE
compliance: [ISO-27001, GDPR, ФЗ-152, PCI-DSS-4]
# SPEC-OPS
deployment-style: kubernetes | vm | serverless | docker-compose | bare-metal
environments:
- { name: dev, purpose: development, scale: minimal }
- { name: staging, purpose: integration-testing, scale: half-prod }
- { name: prod, purpose: production, scale: full }
slo: { availability: "99.9%", error-budget-month: "43m", latency-p95: "300ms" }
observability: { logs: elastic|loki|cloudwatch, metrics: prometheus|datadog|cloudwatch, traces: jaeger|tempo|x-ray }
disaster-recovery: { rto: "<duration>", rpo: "<duration>" }
6.3 SPEC-TEST — стенды и данные¶
Тестовый стенд — не окружение развёртывания, а конструкция доказательства (standard/08 §8.3.2, §8.5.10). Датасет описывается по обе стороны каждой интеграции; ожидаемый результат нередко живёт не в нашей системе, поэтому правила сверки — обязательная часть схемы.
# SPEC-TEST
benches: # топология стенда: узлы, версии, что живое / что эмулируется
- name: "<bench-id>"
nodes: [{ name: "<node>", version: "<version>", mode: live | emulated }]
notes: "<ограничения стенда>"
counterparties: # по одной записи на интеграцию (ровно одна на SPEC-INT)
- integration: SPEC-INT-NN
representation: real | sandbox | emulator
endpoint: "<нативный для носителя pointer>"
fidelity-rationale: "<почему представление отвечает как реальная система>"
datasets: # по обе стороны каждой интеграции
- name: "<dataset-id>"
side: ours | counterparty
integration: SPEC-INT-NN # null для датасета вне интеграции
volume: "<объём>"
origin: synthetic | anonymized-production | client-provided
anonymized: boolean
contains-real-client-data: boolean # true ⇒ client-signature обязательна
retention: "<срок хранения>"
reconciliation-rules: # сверка результатов с данными чужих систем
- name: "<rule-id>"
integration: SPEC-INT-NN
expected-result-source: "<где живёт ожидаемый результат, если не в нашей системе>"
match-keys: []
tolerance: "<допуск сверки>"
run-config:
mocked: [SPEC-INT-NN] # что мокается
live: [SPEC-INT-NN] # что прогоняется вживую
run-order: [] # порядок прогона
seed-mechanism: "<как готовится состояние стенда>"
client-signature: # обязательна при реальных / персональных данных клиента
signed-by: "<name>"
role: "<role>"
organization: "<client-org>"
signed-at: "<ISO-datetime>"
signature-ref: "<ссылка>"
| Правило | Уровень |
|---|---|
Хотя бы один datasets[] с contains-real-client-data: true (или anonymized: false) ⇒ client-signature заполнена; иначе — fatal |
hook-enforced |
counterparties[] — ровно одна запись на каждую интеграцию, представленную на стенде |
hook-enforced |
reconciliation-rules[].expected-result-source непусто, когда ожидаемый результат вне нашей системы |
normative |
Инкремент версии SPEC-TEST инвалидирует verified у TC, ссылающихся на него через environment-ref (standard/10 §10.5.4) |
hook-enforced |
6.4 SPEC-DOC — поставляемая документация¶
SPEC-DOC описывает состав поставляемого результата: документы, которые заказчик получает как часть поставки (standard/08 §8.5.11). Граница с SPEC-OPS — вхождение в состав поставки: руководство администратора — всегда SPEC-DOC, runbook — всегда SPEC-OPS.
# SPEC-DOC
deliverables: # по одной записи на документ
- name: "<document-id>"
kind: user-manual | admin-manual | training-materials | other
audience: "<роль читателя>"
format: pdf | html | markdown | docx | other
language: "<язык поставки>"
required-sections: # обязательные разделы — требование, а не усмотрение исполнителя
- deliverable: "<document-id>"
sections: ["<заголовок обязательного раздела>"]
traces-to: [] # BR / SR / SPEC, поведение которых документ описывает
version-binding:
rule: matches-system-version | matches-release-tag | manual
system-version-ref: "<нативная для носителя ссылка на версию системы>"
acceptance-criteria: # по чему документ принимается; проверяется док-линтом
- criterion: "<проверяемое утверждение>"
checked-by: TC-NN # TC с automation.kind: static (standard/09 §9.8)
| Правило | Уровень |
|---|---|
Док-линт обязателен: у SPEC-DOC существует минимум один TC с automation.kind: static; без него SPEC-DOC неверифицируем и не проходит QG-2 (standard/09 §9.8) |
hook-enforced |
required-sections[] непуст для каждого deliverables[] |
hook-enforced |
traces-to[] непуст: документ описывает поведение, заявленное в требованиях; покрытие ролей и сценариев проверяет док-линт |
normative |
Содержательное соответствие текста реализованному поведению — опционально, через judge-агента (P7 / eval); отдельного механизма не вводится |
normative |
7. ADAPT schema¶
ADAPT — отдельный артефакт (standard/07). Реактивный: существует только при findings от состязательного обзора ТЗ (§7.4.1). Вердикт «no findings» — ADAPT не создаётся; исход обзора в любом случае выпускается как AR (§7.1 ниже), и артефакты ссылаются на неё через <artifact>.source.adversarial-review-ref.
# Identity
id: ADAPT-NNN
title: "Адаптация ТЗ <name>"
type: ADAPT
trigger-stage: import-tz | decompose-br | decompose-sr | spec | tc # стадия-триггер (standard/07 §7.4.1.4)
# Source
source-tz: { id: TZ-YYYY-NNN, signed-date: "<ISO-date>", signed-by-client: "<name-role>", document-version-ref: "<нативный для носителя идентификатор версии>" } # V5 pin
parent-adapt: { id: ADAPT-NNN, delta-tz: TZ-YYYY-NNN } # для delta-ADAPT
# Supersession (standard/07 §7.6.4) — только для superseding-ADAPT
supersedes: ADAPT-MMM # ссылка на дезавуируемый ADAPT
superseded-by: ADAPT-NNN # auto-derived; на дезавуируемом
supersession-rationale: "<противоречащее BR/SR/SPEC + источник>" # mandatory если supersedes присутствует
# Lifecycle (подмножество §1: ADAPT не использует verified/deprecated/obsolete; superseded — терминальное при дезавуировании, §7.6.4)
# Состояние client-ready ИЗЪЯТО: вынесение вопросов клиенту — предмет ACTZ (§7.13), а не состояние ADAPT (standard/10 §10.8.1).
status: draft | review | asked | answered | approved | frozen | superseded
created: "<ISO-date>"
last-updated: "<ISO-date>"
# Approval (required для approved)
approval:
# client-signature ОТСУТСТВУЕТ: ADAPT — внутренняя интерпретация (standard/07 §7.5).
# Клиентские обязательства несёт ACTZ (§7.13) с двусторонней подписью.
architect-signature: { signed-by: "<name>", role: architect, signed-at: "<ISO-datetime>" }
# Auto-derived
generates-requirements: []
generates-specs: []
open-questions-count: integer # должен быть 0 для approved
resolved-questions-count: integer
# AI provenance
ai-provenance: { generated-by: "<vendor>-<model>@<date>", prompt-template: "<template-path>@<version>", context-tokens: integer, output-tokens: integer, human-edits: boolean }
Backward записи внутри body:
id: B-NNN
category: contradiction | gap | hidden-assumption | feasibility | regulatory | terminology | scope
status: open | asked-to-client | answered | resolved | revised | frozen
tz-section: "§N.N"
description: "..."
asked-to-client: "<ISO-date>"
client-answer:
signed-by: "<name>"
signed-at: "<ISO-datetime>"
channel: email | docusign | zoom-transcript | written-letter
text: "..."
resolution: "..." # как ответ интегрирован в Forward
decided-in: "ACTZ-NNN §M" # mandatory для status=resolved; пункт подписанного ACTZ (§7.2)
Находка переходит в resolved только тогда, когда решение по ней вынесено клиенту и подписано: поле decided-in указывает на пункт §M протокола ACTZ в статусе signed (standard/07 §7.13.2). Ссылка на ACTZ в статусе draft запрещена (standard/07 §7.13.4).
7.1 AR schema — запись состязательного обзора¶
AR (standard/07 §7.4.6) — запись-свидетельство, фиксирующая факт и исход обязательного состязательного обзора. Выпускается в обоих исходах; при no-findings она и есть то свидетельство, на которое ссылается <artifact>.source.adversarial-review-ref. Не является артефактом требований и ни в один закрытый список не входит.
# Identity
id: AR-NNN # сквозной в рамках родительского ТЗ; неизменяем
type: AR
tz-ref: TZ-YYYY-NNN # обозреваемое (delta-)ТЗ
trigger-stage: import-tz | decompose-br | decompose-sr | spec | tc # согласовано с ADAPT.trigger-stage
# Reviewer (изоляция: модель ≠ модель основного агента, standard/07 §7.10.2)
reviewer: { vendor: "<provider>", model: "<model-id>" }
# Verdict
verdict: findings-present | no-findings
produces-adapt: [ADAPT-NNN] # mandatory непустой при findings-present; пуст при no-findings
# Lifecycle
status: draft | issued | superseded
superseded-by: AR-NNN # mandatory если status=superseded
# Signature (V6; mandatory для issued)
signature: { author: "<reviewer-id>", timestamp: "<ISO-8601>" }
7.2 ACTZ schema — протокол уточнения ТЗ¶
ACTZ (standard/07 §7.13) — артефакт контрактного контура: порция вопросов, предложений и решений, вынесенная клиенту и подписанная обеими сторонами. Граница с ADAPT проводится по аудитории: показанное клиенту и утверждённое — обязательство, непоказанное — интерпретация. Кардинальность: ТЗ : ACTZ = 1 : 0..N; ADAPT : ACTZ = 1 : 1..N.
# Identity
id: ACTZ-NNN # сквозной в рамках родительского ТЗ; неизменяем
title: "Протокол уточнения ТЗ № N"
type: ACTZ
tz-ref: TZ-YYYY-NNN # обязательно; ТЗ, к которому относится протокол
# Закрываемые находки (conditional)
resolves: # записи B-NNN в ADAPT, которые закрывает протокол
- { id: B-NNN, adapt: ADAPT-NNN } # отсутствует у ACTZ по инициативе клиента (standard/07 §7.13.2)
# Решения (обязательно, непустой)
decisions:
- number: "§M" # стабильный номер пункта; цель ссылки decided-in
statement: "<решение на языке обязательств: «кнопка называется X»>"
tz-section: "§N.N" # уточняемый раздел ТЗ
# Приложения к ТЗ (conditional; standard/07 §7.13.5)
annexes:
- { name: "<приложение>", version: "<новая версия>", document-ref: "<ссылка>" }
# Lifecycle
status: draft | sent | signed | superseded
superseded-by: ACTZ-NNN # mandatory если status=superseded
# Подписи (обязательны для signed; V6)
client-signature: { signed-by: "<name>", role: "<role>", organization: "<client-org>", signed-at: "<ISO-datetime>", signature-ref: "<ссылка>" }
vendor-signature: { signed-by: "<name>", role: "<role>", signed-at: "<ISO-datetime>" }
| Правило | Уровень |
|---|---|
decisions[].number стабилен и неизменяем: на него ссылаются B-NNN.decided-in и AT.verifies[] |
normative |
Подписанный ACTZ неизменяем; исправление — только новым ACTZ с superseded-by на прежнем |
hook-enforced |
Ссылка на ACTZ в статусе draft из decided-in запрещена |
hook-enforced |
resolves[] отсутствует у протокола по инициативе клиента; после подписания решение обязано быть отражено в ADAPT |
normative |
Приложение к ТЗ не адресуется отдельно: его новая версия утверждается через annexes[] той же двусторонней подписью |
normative |
| Итоговое ТЗ = начальное ТЗ (с приложениями) + все подписанные ACTZ; приоритет — у более позднего подписанного документа (standard/07 §7.14) | normative |
8. TC — Test Case¶
# Identity
id: "TC-NN[.N]"
title: "<descriptive>"
type: TC
slug: "<kebab-case>"
# Classification
tc-type: business | ux | system | contract | eval | security # business — прежнее имя acceptance (standard/09 §9.5)
negative: boolean # true для парного негативного TC
# Scope
level: system | subsystem | module
scope: { system: "<system-id>", subsystem: "<subsystem-id>", module: "<module-id>" }
# Lifecycle
status: draft | ready | passing | failing | obsolete
# Verification mapping (≥1)
verifies:
- { id: "<requirement-id>", ref: "<ссылка>", requirement-version: "<version-ref>" } # V5 pinning (standard/03 §3.3.5)
# Pair link (mandatory если negative=false и существует парный)
paired-with: ["<TC-id>"]
# Привязка к задаче (optional; standard/09 §9.19.7)
verifies-tr: "TR-NN" # задача, к объёму которой сужен тест
verifies-claims: [] # подмножество утверждений родительского SR в объёме этой TR
# Стенд и данные (mandatory; standard/09 §9.3, standard/08 §8.5.10)
environment-ref: "SPEC-TEST-NN" # conditional: mandatory если automation.kind: dynamic.
# Для static (док-линт §9.8, структурный TC §9.8.1) не применяется:
# анализатор работает по артефактам, а не против стенда
# Automation
automation:
status: automated | manual-pending
kind: dynamic | static # mandatory; static — runner является статическим анализатором
location: "<path-to-implementation>" # mandatory если automated
runner: pytest | jest | go-test | playwright | vlm-judge | ragas | pact | other
manual-pending-until: "<ISO date>" # mandatory если manual-pending
manual-pending-reason: "<why>"
# Красная история (standard/09 §9.18.2) — условие засчёта TC как доказательства
red-history:
fixing-run: # фиксирующий прогон до реализации
date: "<ISO timestamp>"
result: fail # обязан быть красным; pass → сигнал разбора, не успех
run-ref: "<ссылка>"
green-transition: # записанный переход красный → зелёный
date: "<ISO timestamp>"
run-ref: "<ссылка>"
inherited-from: "TC-NN" # conditional: наследование у задач без изменения поведения
not-applicable-reason: implementation-originated # conditional: только для этого класса; тогда обязателен убитый мутант
mutation-check: { mutants-killed: integer, report-ref: "<ссылка>" } # mandatory при not-applicable-reason
# Execution (mandatory если tc-type=ux | eval; judge.vendor ≠ production model vendor — см. §6.2 SPEC-AI, §9)
judge: { vendor: "<provider>", model: "<model-id>", prompt-template: "<template-path>@<version>" }
baseline: { artifact: "<pointer>", perceptual-diff-threshold: float, metric-thresholds: {} }
# Last run (auto-managed; bot-only)
last-run:
date: "<ISO timestamp>"
result: pass | fail | skipped | n/a
runner-id: "<runner@version>"
run-ref: "<ссылка>"
requirement-version: "<version-ref>"
judge-report: "<for ux/eval>"
# Замена / obsolescence
obsolete-pending: boolean # true при detected delta-ТЗ инвалидации
replaces: "<old-id>"
replaced-by: "<new-id>"
obsoleted-date: "<ISO date>"
# Inherited
ai-provenance: { ... } # см. §1
tc-type: business — каноническое имя; прежнее acceptance в v1.0 не используется. Приёмка против итогового ТЗ выполняется не через TC, а через AT (§8.1).
8.1 AT schema — приёмочный тест контрактного контура¶
AT (standard/09 §9.19) выводится исключительно из итогового ТЗ (standard/07 §7.14): начальное ТЗ с приложениями плюс все подписанные ACTZ (§7.2). AT проверяет соответствие контракту, а не интерпретации, и создаётся изолированным агентом, которому доступ к внутреннему контуру (ADAPT, BR / SR / SPEC, TC, код) запрещён.
# Identity
id: AT-NN # неизменяем
title: "<краткое описательное название>"
type: AT
negative: boolean # обязательно; pos/neg-парность — как у TC (standard/09 §9.7)
# Verification target (обязательно; закрытый список ссылок)
verifies:
- "TZ §N" # раздел итогового ТЗ
- "ACTZ-NNN §M" # пункт подписанного протокола
# Ссылка на внутренний артефакт (BR / SR / SPEC / TC) — fatal (standard/09 §9.19.2)
tz-version: "<редакция итогового ТЗ>" # обязательно; редакция, из которой AT выведен
# Провенанс изолированного агента (обязательно)
generator:
vendor: "<provider>" # обязан отличаться от модели основного агента (зеркально P7)
model: "<model-id>"
internal-contour-access: false # обязательно; подтверждение отсутствия доступа к внутреннему контуру
generated-at: "<ISO-8601>"
# Lifecycle
status: draft | ready | passing | failing | obsolete
# Стенд и датасет приёмочных испытаний (обязательно; standard/09 §9.19.3, §8.5.10).
# Поле заполняет НЕ генератор: изолированный агент внутренних артефактов не видит —
# привязку проставляет архитектор или runner ПОСЛЕ генерации, не нарушая изоляцию.
environment-ref: SPEC-TEST-NN
# Automation (обязательно; прогон только автоматическим runner'ом)
automation:
status: automated | manual-pending
kind: dynamic | static
location: "<path-to-implementation>"
runner: "<runner>"
# Last run (ведёт runner; bot-only)
last-run:
date: "<ISO timestamp>"
result: pass | fail | skipped | n/a
runner-id: "<runner@version>"
run-ref: "<ссылка>"
tz-version: "<редакция итогового ТЗ на момент прогона>"
Тело AT обязательно содержит раздел с дословной цитатой проверяемого пункта итогового ТЗ (tz_text) рядом с шагами проверки (standard/09 §9.19.3).
| Правило | Уровень |
|---|---|
verifies[] содержит только TZ §N и ACTZ-NNN §M; ссылка на внутренний артефакт — fatal |
hook-enforced |
generator.internal-contour-access: true — fatal: изоляция есть суть механизма, а не гигиена |
hook-enforced |
generator.model ≠ модель основного агента |
hook-enforced |
AT перегенерируются перед каждыми испытаниями; tz-version обязана совпадать с действующей редакцией итогового ТЗ, иначе испытания блокируются |
hook-enforced |
Продукт не предъявляется к сдаче, пока не все AT в статусе passing (standard/10 §10.4.3) |
normative |
9. Validation rules (cross-field)¶
Правила, не выражаемые в чистой JSON Schema; требуют custom validator. Колонка «Формальная проверка» даёт исполнимый предикат или ссылку на готовый KG-запрос (reference/05 §5/§6).
| Правило | Описание | Формальная проверка |
|---|---|---|
| ID неизменяем | При изменении файла поле id не меняется. |
diff(prev.id, curr.id) == ∅ |
parent exists |
Для SR — parent BR существует и в статусе ≥ approved. |
status(BR[SR.parent.id]) ≥ approved; orphans — 05 §6.1 |
source.adapt approved |
Для BR/SR/SPEC — ADAPT в source.adapt в статусе approved/frozen. |
status(ADAPT[art.source.adapt]) ∈ {approved, frozen} |
verified-by consistency |
TC в verified-by имеют verifies[].id = этот артефакт. |
∀ tc ∈ art.verified-by: art.id ∈ tc.verifies[].id |
requirement-version lock |
TC.last-run.requirement-version = verifies[].requirement-version. |
tc.last-run.requirement-version == tc.verifies[].requirement-version; stale — 05 §4.4 |
source.adapt для BR/SR/SPEC (conditional) |
Канонический источник ADAPT при наличии findings; при вердикте «no findings» — source.adversarial-review-ref (standard/07 §7.4.1). TR — через parent SR (standard/06 §6.6.2). |
art.type ∈ {BR, SR, SPEC-*} ⇒ art.source.adapt ≠ null ∨ art.source.adversarial-review-ref ≠ null |
| SPEC-AI requires ai-act | Для AI-артефакта ai-act.risk-class обязательно. |
art.type == SPEC-AI ⇒ art.ai-act.risk-class ≠ null |
| Data residency consistency | RU в SR.data-classification.data-residency ⇒ то же в parent BR. |
'RU' ∈ SR.…data-residency ⇒ 'RU' ∈ BR[SR.parent].…data-residency |
| Compliance hierarchy | SR.compliance ⊆ parent BR.compliance (или явный justification). |
SR.compliance ⊆ BR[parent].compliance ∨ exists(extension-justification) |
TC automated requires location |
automation.status: automated ⇒ automation.location непустое. |
tc.automation.status == 'automated' ⇒ tc.automation.location ≠ '' |
| Negative TC обязателен | На каждое нормативное утверждение — TC с negative: true. |
∀ assertion ∈ art: ∃ tc(negative: true) (standard/09 §9.7) |
| ADAPT open-questions == 0 for approved | Approval блокируется при open / asked-to-client / answered / revised backward: все находки обязаны быть в resolved (standard/07 §7.4.5, standard/10 §10.8.2). |
adapt.status == approved ⇒ count(backward[status ∈ {open, asked-to-client, answered, revised}]) == 0 (05 §4.7) |
| Дезавуирование корректно | supersedes ⇒ непустой supersession-rationale и симметричный superseded-by на цели; нет висячих source.adapt на superseded (standard/07 §7.6.4, standard/10 §10.8.5). |
adapt.supersedes ≠ null ⇒ adapt.supersession-rationale ≠ '' ∧ ADAPT[adapt.supersedes].superseded-by == adapt.id; ∄ art: art.source.adapt = X ∧ status(ADAPT[X]) == superseded |
| Judge isolation (SPEC-AI) | judge.vendor ≠ production-model.vendor. |
tc.judge.vendor ≠ SPEC-AI[tc.verifies].production-model.vendor |
| SPEC depends-on acyclic | Граф depends-on между SPEC — DAG. |
cypher cycle-detection (05 §4.6): rows ≠ ∅ ⇒ нарушение |
Находка resolved решена подписанным ACTZ |
Обратная находка в статусе resolved обязана нести decided-in: ACTZ-NNN §M, и целевой ACTZ обязан быть в статусе signed (standard/07 §7.13.2). |
b.status == resolved ⇒ b.decided-in ≠ null ∧ status(ACTZ[b.decided-in]) == signed ∧ b.decided-in.§M ∈ ACTZ.decisions[].number |
ACTZ signed двусторонне подписан |
Оба поля подписи заполнены; подписанный протокол неизменяем. | actz.status == signed ⇒ actz.client-signature ≠ null ∧ actz.vendor-signature ≠ null |
| AT ссылается только на контракт | AT.verifies[] содержит только TZ §N / ACTZ-NNN §M; ссылка на внутренний артефакт — fatal (standard/09 §9.19.2). |
∀ v ∈ at.verifies: v ~ /^(TZ §|ACTZ-\d{3} §)/; at.generator.internal-contour-access == false |
| AT свеж относительно итогового ТЗ | AT.tz-version = действующая редакция итогового ТЗ; расхождение блокирует испытания (standard/09 §9.19.4). |
at.tz-version == effective-tz.version |
| Красная история — условие засчёта TC | TC засчитывается как доказательство при QG-2 только с записанным переходом красный → зелёный; исключение — класс implementation-originated с убитым мутантом (standard/09 §9.18.2). |
tc.red-history.green-transition ≠ null ∨ tc.red-history.inherited-from ≠ null ∨ (tc.red-history.not-applicable-reason == implementation-originated ∧ tc.red-history.mutation-check.mutants-killed ≥ 1) |
implementation-originated не наблюдаем клиентом |
Класс легализует внутреннюю деталь; наблюдаемое клиентом поведение через него запрещено (standard/06 §6.13.2). | art.source.implementation-originated ≠ null ⇒ observable-by-client == false ∧ human-approval ≠ null ∧ mutation-check.mutants-killed ≥ 1 |
| Динамический TC привязан к стенду | TC с automation.kind: dynamic несёт environment-ref на существующий SPEC-TEST: «тест пройден» имеет смысл только против конкретного стенда и конкретных данных (standard/09 §9.3). Отсутствие поля у динамического TC — fatal. Статические проверки (док-линт, структурный TC) стенда не требуют. |
tc.automation.kind == 'dynamic' ⇒ tc.environment-ref ≠ null ∧ type(SPEC[tc.environment-ref]) == 'SPEC-TEST' |
| Реальные данные клиента подписаны клиентом | SPEC-TEST, где хотя бы один датасет несёт реальные или персональные данные клиента, обязан нести client-signature; объём и анонимизация — решение клиента, не исполнителя (standard/08 §8.5.10). Отсутствие подписи — fatal. |
∃ d ∈ spec.datasets: d.contains-real-client-data == true ∨ d.anonymized == false ⇒ spec.client-signature ≠ null |
| SPEC-DOC покрыт док-линтом | У SPEC-DOC существует минимум один TC-док-линт (automation.kind: static); без него SPEC-DOC неверифицируем и не проходит QG-2 (standard/09 §9.8). |
spec.type == 'SPEC-DOC' ⇒ ∃ tc ∈ spec.verified-by: tc.automation.kind == 'static' |
10. Изоморфизм носителя¶
Отображение для git (YAML frontmatter) ↔ document-oriented store (JSON document):
| Поле (canonical) | git (YAML frontmatter) | Document store (JSON doc) |
|---|---|---|
id |
id |
_id = <project>:<doc-type>:<slug>, поле slug |
type: BR |
type: BR |
level: "business" |
type: SPEC-API |
type: SPEC-API |
doc_type: "spec_api" |
parent.id |
parent.id |
parent |
children |
(auto-derived) | children (auto-derived) |
status |
status |
status |
priority |
priority |
priority |
source.adapt |
source.adapt |
created_from_adapt |
constrained-by[] |
constrained-by |
constrained_by (subdoc array) |
verified-by[] |
(auto-derived) | linked_tests |
ai-provenance.* |
nested object | nested subdocument |
compliance |
compliance array |
compliance subdoc |
data-classification |
nested object | nested subdoc |
business-outcome |
nested object | nested subdoc |
replaces / replaced-by |
string ID | replaces / replaced_by |
Нативные для носителя имена полей могут отличаться, но семантика и invariants сохраняются через capabilities V1-V6 (01-glossary.md §2.7).
11. Schema versioning¶
Каждый артефакт имеет поле schema-version (semver). При несовпадении версии файла и текущей схемы validator предлагает migration.
| Изменение | Bump |
|---|---|
| Новое необязательное поле | minor (1.0 → 1.1) |
| Новое обязательное поле | major (1.0 → 2.0) + migration script |
| Удаление поля | major + migration script |
| Изменение enum | minor если добавление, major если удаление |
| Переименование поля | major + migration script |
Текущая версия schemas: 1.0.
12. JSON Schema fragment example (BR)¶
Ключевые patterns (полная BR-схема — reference/schemas/br.json, планируется):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://renar.tech/schemas/br.json",
"type": "object",
"required": ["id", "title", "type", "status", "priority", "source", "ai-provenance"],
"properties": {
"id": { "type": "string", "pattern": "^BR-[0-9]{2}(\\.[0-9]+)?$" },
"title": { "type": "string", "minLength": 5, "maxLength": 100 },
"type": { "const": "BR" },
"status": { "enum": ["draft", "review", "approved", "verified", "deprecated", "obsolete"] },
"priority": { "enum": ["must", "should", "could"] },
"source": { "type": "object", "required": ["tz-section"], "properties": { "adapt": { "pattern": "^ADAPT-[0-9]{3}(-delta-[0-9]+)?$" } } },
"ai-provenance": { "required": ["generated-by", "generated-at"], "properties": { "generated-by": { "pattern": "^[a-z]+-[a-z0-9-]+@[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } }
}
}
Аналогичные JSON-схемы для SR/TR/SPEC-*/TC/ADAPT — в reference/schemas/ (планируется).
Schemas reference RENAR 1.0 — см. также 01-glossary.md, standard/06-09 для нормативных определений.