2026-08-11 12:00:00 +00:00
|
|
|
|
# schema.yaml — single source of truth for artifact frontmatter.
|
|
|
|
|
|
# Stage 1 of ADR-0004: scripts/validate.py checks generically against this
|
|
|
|
|
|
# file. Extending the framework's metadata means editing THIS file, not code.
|
|
|
|
|
|
# Agents: never invent fields or status values; propose a schema change.
|
|
|
|
|
|
#
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# PROJEKTERWEITERUNGEN gegenüber neckbeard v0.3.1 (Original:
|
|
|
|
|
|
# docs/sources/upstream/neckbeard-v0.3.1/schema.yaml; Design:
|
2026-08-11 12:00:00 +00:00
|
|
|
|
# docs/design/done/2026-08-11-neckbeard-migration.md, ADR-0012/0013):
|
2026-08-11 12:00:00 +00:00
|
|
|
|
# * issue: Pflichtfelder milestone (M1–M5) + priority; Status-Enum um
|
|
|
|
|
|
# next/waiting erweitert; due/host/area/wartegrund/gitlab_iid;
|
|
|
|
|
|
# Regel waiting_requires_reason; globale Regel wip_limit (max. 2
|
|
|
|
|
|
# in-progress) in validate.py.
|
2026-08-18 12:00:00 +00:00
|
|
|
|
# * issue.projekt (ADR-0019): Herkunfts-Projekt adoptierter
|
|
|
|
|
|
# Komponenten-Issues; zusammen mit gitlab_iid die Spiegel-Adresse.
|
|
|
|
|
|
# Fehlt das Feld, ist management gemeint.
|
2026-08-11 12:00:00 +00:00
|
|
|
|
# * component: neuer Typ unter docs/components/ (Dateiname = Slug).
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# * wiki-page: Area-Enum um "vision" erweitert; Status-Enum um
|
|
|
|
|
|
# "declined" erweitert (Rahmenwerk geprueft, deckt nicht ab — das
|
|
|
|
|
|
# Muster bleibt bestehen). Begruendung steht am Feld selbst.
|
|
|
|
|
|
# ⚠️ status/harvested_in fehlten nach dem v0.3.1-Merge ganz und sind
|
|
|
|
|
|
# hier nachgetragen; HERKUNFT.md kann das nicht mitfuehren, weil sie
|
|
|
|
|
|
# unter docs/sources/ gesperrt ist, waehrend ADR-0024 ihre Tabelle
|
|
|
|
|
|
# fuer massgeblich erklaert. Widerspruch, als Befund notiert.
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# * project_section_marker auf unsere Marke gesetzt; ledger und
|
|
|
|
|
|
# verdict unverändert von upstream übernommen (v0.3.1).
|
2026-08-11 12:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
version: 1
|
|
|
|
|
|
|
|
|
|
|
|
scope:
|
|
|
|
|
|
# Files considered artifacts. Templates and raw sources are exempt.
|
|
|
|
|
|
include:
|
|
|
|
|
|
- "PROJECT.md"
|
|
|
|
|
|
- "docs/**/*.md"
|
|
|
|
|
|
exclude:
|
|
|
|
|
|
- "**/template.md"
|
|
|
|
|
|
- "docs/sources/**"
|
|
|
|
|
|
- "vendor/**"
|
|
|
|
|
|
# Files whose inline links are checked, but which need no frontmatter
|
|
|
|
|
|
# (root-level prose: README, AGENTS, WORKFLOW, generated STATUS, ...).
|
|
|
|
|
|
link_only:
|
|
|
|
|
|
- "*.md"
|
|
|
|
|
|
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# Files an adopting project holds byte-identical against its vendored
|
|
|
|
|
|
# baseline (AGENTS.md §5). They are copied into repositories that do not
|
|
|
|
|
|
# have this repo's docs/, so they must carry no repo-relative link — a
|
|
|
|
|
|
# link that resolves here and nowhere else makes the adoption path
|
|
|
|
|
|
# unfollowable. Mention an ADR by its identifier instead.
|
|
|
|
|
|
vendored:
|
|
|
|
|
|
- "AGENTS.md"
|
|
|
|
|
|
- "WORKFLOW.md"
|
|
|
|
|
|
- "CLAUDE.md"
|
|
|
|
|
|
|
|
|
|
|
|
# An adopting project appends its own always-on rules below a marker in a
|
|
|
|
|
|
# vendored file (AGENTS.md §5). Everything from the marker on belongs to
|
|
|
|
|
|
# that project, is never copied anywhere, and may link freely — the rule
|
|
|
|
|
|
# above applies only to the upstream part. Adopters set their own marker.
|
|
|
|
|
|
project_section_marker: "<!-- projektabschnitt -->"
|
|
|
|
|
|
|
2026-08-11 12:00:00 +00:00
|
|
|
|
# Frontmatter fields whose values are links. Values starting with
|
|
|
|
|
|
# http://, https:// or mailto: are treated as external and only
|
|
|
|
|
|
# format-checked; everything else must be a repo-root-relative path
|
|
|
|
|
|
# to an existing file.
|
2026-08-21 12:00:00 +00:00
|
|
|
|
link_fields: [related, sources, supersedes, superseded_by, judged]
|
2026-08-11 12:00:00 +00:00
|
|
|
|
|
|
|
|
|
|
types:
|
|
|
|
|
|
project:
|
|
|
|
|
|
dir: "."
|
|
|
|
|
|
filename: "^PROJECT\\.md$"
|
|
|
|
|
|
required: [type, language, size_s_exception, purpose, audience]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
language: { enum: [de, en] }
|
|
|
|
|
|
size_s_exception: { kind: bool }
|
|
|
|
|
|
purpose: { kind: str }
|
|
|
|
|
|
audience: { kind: str }
|
|
|
|
|
|
|
|
|
|
|
|
adr:
|
|
|
|
|
|
dir: "docs/adr"
|
|
|
|
|
|
filename: "^\\d{4}-[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, id, status, date]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
id: { pattern: "^\\d{4}$" }
|
|
|
|
|
|
status: { enum: [proposed, accepted, superseded] }
|
|
|
|
|
|
date: { kind: date }
|
|
|
|
|
|
supersedes: { kind: link, nullable: true }
|
|
|
|
|
|
superseded_by: { kind: link, nullable: true }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
rules:
|
|
|
|
|
|
# status: superseded requires superseded_by to point at the successor.
|
|
|
|
|
|
- superseded_requires_pointer
|
|
|
|
|
|
|
|
|
|
|
|
design:
|
|
|
|
|
|
dir: "docs/design"
|
|
|
|
|
|
filename: "^\\d{4}-\\d{2}-\\d{2}-[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, status, date, size]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
status: { enum: [gate-1, gate-2, gate-3, gate-4, gate-5, done] }
|
|
|
|
|
|
size: { enum: [L] }
|
|
|
|
|
|
date: { kind: date }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
rules:
|
|
|
|
|
|
# status: done if and only if the file lives under docs/design/done/.
|
|
|
|
|
|
- done_iff_in_done_dir
|
|
|
|
|
|
|
|
|
|
|
|
aar:
|
|
|
|
|
|
dir: "docs/aar"
|
|
|
|
|
|
filename: "^\\d{4}-\\d{2}-\\d{2}-[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, status, date]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
status: { enum: [open, harvested] }
|
|
|
|
|
|
date: { kind: date }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
|
|
|
|
|
|
issue:
|
|
|
|
|
|
dir: "docs/issues"
|
|
|
|
|
|
filename: "^\\d{4}-[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, id, status, created, milestone, priority]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
id: { pattern: "^\\d{4}$" }
|
|
|
|
|
|
status: { enum: [open, next, in-progress, waiting, done, rejected] }
|
|
|
|
|
|
created: { kind: date }
|
|
|
|
|
|
milestone: { enum: [M1, M2, M3, M4, M5] }
|
|
|
|
|
|
priority: { enum: [high, medium, low] }
|
|
|
|
|
|
due: { kind: date, nullable: true }
|
|
|
|
|
|
host: { enum: [cfgmon, overmind, matrix, game], nullable: true }
|
|
|
|
|
|
area: { enum: [security, infrastructure, database, element], nullable: true }
|
|
|
|
|
|
wartegrund: { kind: str, nullable: true }
|
2026-08-18 12:00:00 +00:00
|
|
|
|
projekt: { enum: [gitops, threadnet-web, threadnet-call], nullable: true }
|
2026-08-11 12:00:00 +00:00
|
|
|
|
gitlab_iid: { pattern: "^\\d+$", nullable: true }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
rules:
|
|
|
|
|
|
# status: waiting requires a named reason (old rule: "nur mit
|
|
|
|
|
|
# benanntem Grund").
|
|
|
|
|
|
- waiting_requires_reason
|
|
|
|
|
|
|
|
|
|
|
|
component:
|
|
|
|
|
|
dir: "docs/components"
|
|
|
|
|
|
filename: "^[A-Za-z0-9.-]+\\.md$"
|
|
|
|
|
|
required: [type, slug, anzeigename, phase]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
slug: { kind: str }
|
|
|
|
|
|
anzeigename: { kind: str }
|
|
|
|
|
|
phase: { enum: [active, staged, external] }
|
|
|
|
|
|
gitlab: { kind: str }
|
|
|
|
|
|
mirror: { kind: str, nullable: true }
|
2026-08-19 12:00:00 +00:00
|
|
|
|
# Repo traegt fremde Historie (z. B. durch einen Upstream-Merge). Der Wert ist
|
|
|
|
|
|
# die Begruendung, kein Schalter: Die Git-Hygiene-Pruefung nimmt hier Commits
|
|
|
|
|
|
# aus, die nicht von eigenen Identitaeten committet wurden — wer das erklaert,
|
|
|
|
|
|
# soll sagen, woher die fremden Commits stammen.
|
|
|
|
|
|
fremdhistorie: { kind: str, nullable: true }
|
2026-08-11 12:00:00 +00:00
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
rules:
|
|
|
|
|
|
# The canonical slug is the filename — no second naming scheme.
|
|
|
|
|
|
- slug_matches_filename
|
|
|
|
|
|
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# One per session. The envelope is validated here; the gate rows and
|
|
|
|
|
|
# ladder entries in the body are outside what this engine can express
|
|
|
|
|
|
# (it has no notion of a list of records) and belong to scripts/judge.py.
|
|
|
|
|
|
# That seam is deliberate — see ADR-0010.
|
|
|
|
|
|
ledger:
|
|
|
|
|
|
dir: "docs/ledger"
|
|
|
|
|
|
filename: "^\\d{4}-\\d{2}-\\d{2}-[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, date, size, status]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
date: { kind: date }
|
|
|
|
|
|
size: { enum: [S, M, L] }
|
|
|
|
|
|
status: { enum: [open, closed] }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
|
|
|
|
|
|
# The output of a judged run. Categories are the two-bucket
|
|
|
|
|
|
# classification the harvest assessment established: a finding is either
|
|
|
|
|
|
# the model not following a clear rule, or a gap in the framework.
|
|
|
|
|
|
verdict:
|
|
|
|
|
|
dir: "docs/verdict"
|
|
|
|
|
|
filename: "^\\d{4}-\\d{2}-\\d{2}-[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, date, outcome, judged]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
date: { kind: date }
|
|
|
|
|
|
outcome: { enum: [clean, model-failure, framework-gap, both] }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
|
2026-08-11 12:00:00 +00:00
|
|
|
|
wiki-page:
|
|
|
|
|
|
dir: "docs/wiki"
|
|
|
|
|
|
filename: "^[a-z0-9-]+\\.md$"
|
|
|
|
|
|
required: [type, area]
|
|
|
|
|
|
fields:
|
|
|
|
|
|
area:
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- index
|
|
|
|
|
|
- architecture
|
|
|
|
|
|
- admin
|
|
|
|
|
|
- deployment
|
|
|
|
|
|
- user-guide
|
|
|
|
|
|
- requirements
|
|
|
|
|
|
- faq
|
|
|
|
|
|
- stolpersteine
|
|
|
|
|
|
- vision
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# Aus neckbeard v0.3.1 (ADR-0009): Ernte-Stand eines wiederkehrenden
|
|
|
|
|
|
# Musters. `harvested` heisst, eine VEROEFFENTLICHTE Version deckt es
|
|
|
|
|
|
# ab — uebergeben ist nicht geerntet —, und `harvested_in` nennt sie.
|
|
|
|
|
|
#
|
|
|
|
|
|
# PROJEKTERWEITERUNG: vierter Wert `declined`. Ein Muster, das das
|
|
|
|
|
|
# Rahmenwerk geprueft und nicht uebernommen hat, ist weder offen (es
|
|
|
|
|
|
# ist entschieden) noch geerntet (es kommt nie). Es als `open` zu
|
|
|
|
|
|
# fuehren behauptet einen Vorgang, den es nicht mehr gibt. Bewusst
|
|
|
|
|
|
# NICHT `rejected` wie beim Issue-Typ: ein abgelehntes Issue ist
|
|
|
|
|
|
# erledigt, ein `declined` Muster besteht weiter und bleibt unseres.
|
|
|
|
|
|
status: { enum: [open, partly, harvested, declined] }
|
|
|
|
|
|
harvested_in: { kind: str }
|
2026-08-11 12:00:00 +00:00
|
|
|
|
sources: { kind: links }
|
|
|
|
|
|
related: { kind: links }
|
|
|
|
|
|
rules:
|
|
|
|
|
|
# Pages other than the index should be linked from somewhere
|
|
|
|
|
|
# (reported as WARNING, not error — see validate.py).
|
|
|
|
|
|
- warn_if_orphan
|
2026-08-21 12:00:00 +00:00
|
|
|
|
# PROJEKTERWEITERUNG: harvested und declined behaupten beide eine
|
|
|
|
|
|
# gefallene Entscheidung und muessen die Version nennen, in der sie
|
|
|
|
|
|
# fiel. Ohne das ist "geerntet" nicht von "uebergeben" zu trennen.
|
|
|
|
|
|
- entschiedener_stand_braucht_beleg
|