# 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. # # PROJEKTERWEITERUNGEN gegenüber neckbeard v0.3.1 (Original: # docs/sources/upstream/neckbeard-v0.3.1/schema.yaml; Design: # docs/design/done/2026-08-11-neckbeard-migration.md, ADR-0012/0013): # * issue: Pflichtfelder milestone (M1–M6) + 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. # * issue.projekt (ADR-0019): Herkunfts-Projekt adoptierter # Komponenten-Issues; zusammen mit gitlab_iid die Spiegel-Adresse. # Fehlt das Feld, ist management gemeint. # * component: neuer Typ unter docs/components/ (Dateiname = Slug). # * 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. # * project_section_marker auf unsere Marke gesetzt; ledger und # verdict unverändert von upstream übernommen (v0.3.1). 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" # 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: "" # 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. link_fields: [related, sources, supersedes, superseded_by, judged] 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, M6] } 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 } projekt: { enum: [gitops, threadnet-web, threadnet-call], nullable: true } 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 } # 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 } related: { kind: links } rules: # The canonical slug is the filename — no second naming scheme. - slug_matches_filename # 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 } 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 # 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 } 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 # 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