Spec Format Reference
Specs are YAML files validated against a JSON Schema (notarai.spec.json). The format uses progressive disclosure: a small set of required fields for minimum viability, with optional fields for precision as needed.
Required fields
schema_version
Pins the JSON Schema version. Current version: "0.8". Versions "0.7", "0.6", and "0.5" are also accepted for backward compatibility.
schema_version: '0.8'
intent
Natural language description of what the system or feature should do.
intent: |
Users can sign up, log in, and reset passwords.
Sessions expire after 30 min of inactivity.
behaviors
Structured Given/Then entries describing expected behavior. Each behavior has a name, a given condition, and a then outcome. Required for full tier specs; optional for registered and derived tier specs.
behaviors:
- name: 'signup'
given: 'valid email + password (>= 12 chars)'
then: 'account created, welcome email sent'
- name: 'session_timeout'
given: '30 min inactivity'
then: 'session invalidated'
Behaviors may also include optional interaction and state_transition sub-fields:
behaviors:
- name: 'submit_form'
given: 'user submits a valid form'
then: 'data saved, confirmation shown'
interaction:
trigger: user_action # user_action | timer | system_event | data_change | schedule | external_signal | threshold | manual | lifecycle
sequence:
- validate fields
- post to API
- show confirmation
state_transition:
from: editing
to: confirmed
Behaviors may also declare the tests that verify them via tested_by
(introduced in schema 0.8). notarai check uses this to surface
test-alignment drift:
behaviors:
- name: 'signup'
given: 'valid email and password'
then: 'account created, welcome email sent'
tested_by:
- path: 'tests/auth/signup_test.rs'
assertion: 'signup_creates_account'
| Check | Severity | Trigger |
|---|---|---|
| T001 | Warning | A tier-1 behavior has no tested_by entry. |
| T002 | Error | A tested_by.path does not exist on disk. |
artifacts
Glob patterns mapping the spec to the files it governs. The schema accepts any string as a category key. Convention categories:
| Category | When to use |
|---|---|
code | Source code |
docs | Documentation |
tests | Test files |
slides | Presentation files |
data | Data files, CSVs |
configs | Configuration, IaC |
notebooks | Jupyter/R notebooks |
assets | Media, images, fonts |
templates | Reusable templates |
schemas | Data schemas, API specs |
artifacts:
code:
- path: 'src/auth/**'
role: 'primary implementation'
docs:
- path: 'docs/auth.md'
tests:
- path: 'tests/auth/**'
Each artifact ref may include an optional integer tier override (1-4) for files that belong to a different tier than the spec itself:
artifacts:
code:
- path: 'dist/bundle.js'
tier: 4 # derived output — tracked for staleness, not authored directly
Optional fields
constraints
Rules the system must follow.
constraints:
- 'rate limit: 5 login attempts per minute per IP'
- 'passwords must be >= 12 characters'
invariants
Conditions that must never be violated.
invariants:
- 'no plaintext passwords stored anywhere'
- 'all API responses include request-id header'
decisions
Architectural decision log with date, choice, and rationale.
decisions:
- date: '2025-01-15'
choice: 'JWT over session cookies'
rationale: 'Stateless auth simplifies horizontal scaling'
open_questions
Unresolved design questions.
open_questions:
- 'Should we support OAuth providers beyond Google?'
- "What's the session timeout for mobile clients?"
dependencies
References to other specs this one interacts with.
dependencies:
- $ref: 'billing.spec.yaml'
relationship: 'auth gates billing endpoints'
notes
Freeform hints for the LLM about implicit relationships.
notes: |
The auth module shares a rate limiter with the API gateway.
Session storage is Redis in production, in-memory in dev.
output
Describes what the spec ultimately produces. Useful for non-software artifacts like presentations or reports.
output:
type: presentation # app | presentation | interactive-doc | game | dashboard | report | library | service | document | course | api | infrastructure | dataset | design-system | campaign | template
format: pptx
runtime: static-file # browser | native | static-file | embedded | server
entry_point: dist/deck.pptx
content
Describes the output’s logical structure in content terms (slides, scenes, sections) rather than file terms.
content:
structure: graph # ordered | hierarchical | graph | free-form
sections:
- id: level_1
type: scene
intent: 'Tutorial level introducing movement mechanics'
duration: { value: 5, unit: minutes }
connections:
- to: level_2
label: completion
- to: game_over
label: player_death
depends_on:
- id: intro_cutscene
relationship: 'must complete before this section unlocks'
evidence:
- type: data
source: playtests/run_3.csv
claim: '85% of players complete within 5 minutes'
states
Top-level state machine definition for interactive artifacts.
states:
initial: idle
definitions:
- id: idle
transitions:
- to: running
on: start
guard: 'all required fields are populated'
action: 'initialize timer, log start event'
- id: running
transitions:
- to: idle
on: stop
design
Visual and design specifications for brand-governed artifacts.
design:
theme:
palette: ['#1a1a2e', '#16213e']
typography:
heading: Inter
body: Roboto
modes:
light: { palette: ['#ffffff', '#f0f0f0'] }
dark: { palette: ['#1a1a2e', '#16213e'] }
layout:
type: paginated # slide-deck | scrolling | spatial | grid | free-form | paginated | canvas | timeline | tabbed
dimensions: letter
print:
margins: { top: '1in', right: '1in', bottom: '1in', left: '1in' }
headers: true
footers: true
page_numbers: true
responsive:
breakpoints:
- name: mobile
max_width: 768
layout_override: scrolling
- name: desktop
min_width: 769
audience
Context about who the output is for.
audience:
role: 'Series B investors'
assumed_knowledge: 'Familiar with SaaS metrics, not technical infrastructure'
tone: formal-but-engaging
locale: en-US
accessibility:
- high-contrast
- screen-reader-friendly
variants
Multiple versions of the same artifact with selective field overrides.
variants:
- id: investor-deck
description: 'Condensed version for investor meetings'
overrides:
audience.role: 'Series B investors'
- id: engineering-deep-dive
description: 'Full technical version for the eng team'
Variants are declarative metadata by default. Set variants_resolved: true at the spec top level to opt in to programmatic override resolution (scalar replacement, array replacement with + prefix for append, deep merge for objects, null to clear).
pipeline
Describes the build or generation process for the output artifact.
pipeline:
env:
NODE_ENV: production
steps:
- name: compile
tool: tsc
input: 'src/**/*.ts'
output: dist/
condition: "output.format == 'web'"
- name: export_pdf
command: 'pandoc input.md -o output.pdf'
condition: "output.format == 'pdf'"
on_failure: skip
depends_on: [compile]
env:
PANDOC_DATA_DIR: ./templates
preview:
command: npx serve dist/
url: 'http://localhost:3000'
feedback
Connects output performance metrics back to the spec for reconciliation triggers.
feedback:
metrics:
- name: avg_completion_rate
source: analytics/completion.csv
threshold: '>= 0.7'
- name: build_time
threshold: '< 5s'
triggers:
- condition:
metric: avg_completion_rate
operator: below_threshold
duration: { value: 3, unit: days }
action: reconcile
priority: high
Note: reconciliation_trigger (free-form string) is deprecated in favor of triggers but still accepted.
compliance
Maps invariants and constraints to regulatory or standards frameworks. The reconciliation engine verifies that framework-required invariants still exist in the spec.
compliance:
frameworks:
- name: SOC2
controls:
- id: CC6.1
satisfied_by:
invariants: ['no plaintext passwords stored anywhere']
constraints: ['rate limit: 5 login attempts per minute per IP']
- name: WCAG
level: AA
satisfied_by:
invariants: ['all interactive elements have visible focus indicators']
audit_trail: true
Coverage tiers
Every file in the repo falls into one of four tiers:
- Tier 1 (Full) — Business logic, APIs, user-facing features. Full behavioral specification required.
- Tier 2 (Registered) — Utilities, config, sidecars. Intent and artifact mapping only;
behaviorsnot required. - Tier 3 (Excluded) — Explicitly out of scope. Declared via
excludeglobs on the system spec. - Tier 4 (Derived) — Generated outputs tracked for staleness but not authored directly (e.g., build artifacts, compiled bundles). Use
tier: derivedon the spec ortier: 4on individual artifact refs.
Files not covered by any tier are flagged as “unspecced” — a lint warning, not a blocker.
Set the spec-level tier with the tier field:
tier: registered # full (default) | registered | derived
Composition
Specs compose via $ref (borrowed from JSON Schema/OpenAPI):
subsystems— hierarchical references (system → services)applies— cross-cutting specs (e.g., security, logging) that apply to all subsystems
A top-level system.spec.yaml serves as the manifest, referencing subsystem specs and declaring exclusion patterns for Tier 3 files.
Cross-cutting specs
A spec that expresses concerns spanning multiple subsystems (style, security, logging, compliance) should set cross_cutting: true:
schema_version: '0.8'
cross_cutting: true
intent: >
American English spelling across all code and documentation.
behaviors:
- name: american_english
given: 'british spelling appears in a governed file'
then: 'reconciliation flags it as drift'
invariants:
- 'All documentation uses American English spellings throughout'
Cross-cutting specs:
- Omit
artifacts— they govern no files directly. Their invariants and behaviors layer onto the specs that include them viaapplies. - Cannot be top-level — they must not declare
subsystemsorexclude. - Must be referenced via
applies, notsubsystems— L011 flags misplacement.
This avoids glob overlap with subsystem specs (since two specs governing the same file raises an OverlappingCoverage finding) while still letting the spec layer its invariants across the whole system.