Reconcile the decision reversibility field — free-text prose vs. the @dossier/okf enum

0017-reversibility-schema-conformance

decision read as Explain confidence verified status active 2026-06-19 owner knowledge-architect
Reversibility
two-way door

DEC-0017 — Reversibility field: free-text prose vs. the OKF enum

Reversibility: two-way door — the choice of conformance strategy (relax / split / normalize) is itself reversible; the data could be re-shaped again if a later need (e.g. richer mixed-door modelling) argues for splitting the field. The captured why is not lost under any option.

Status: active / resolved (2026-06-19). Option 3 (normalize the data) was chosen and applied: reversibility is a strict door classifier in frontmatter; the captured nuance lives in a body **Reversibility:** <door> — <why> line. Conformed across 40 decision records + the @dossier/okf schema doc-comment in commit 6b1d662; pnpm kb:check now reports the KB clean. Closes Resolve the decision `reversibility` schema conformance gap. The keystone parser found the gap; the Principal Knowledge-Format Architect adjudicated. See the audit: OKF Integrity Audit — knowledge/ against @dossier/okf parse() (2026-06-14).

Context

The OKF Integrity Audit — knowledge/ against @dossier/okf parse() (2026-06-14) ran @dossier/okf parse() over knowledge/**/*.md. At the time, nine decision atoms failed schema validation because the reversibility field carried free text rather than the enum; by 2026-06-19 the affected set had grown to ~40 ADRs as the corpus expanded (the prose form was the de-facto authoring convention).

  • The schema (packages/okf/src/schema.ts): reversibilityValues = ['one-way door', 'two-way door', 'one-way', 'two-way'], exposed as a strict z.enum. A package test ("validates a decision atom with prose reversibility") asserts only the bare enum forms pass.
  • The data: the affected records append a parenthetical rationale to the enum, e.g. two-way door (the generator is swappable — the OKF git repo is the source of truth …). This is a genuinely useful piece of captured judgment (it says why it's a two-way door), which is exactly the tacit-knowledge the model exists to preserve (Dossier — The Knowledge Model (v0) principle 7).
  • Affected (verified by grep): 0004, 0008, 0009, 0011, 0012, 0013, 0014, 0015, 0016. Bare-enum records (0001–0003, 0005–0007, 0010) pass.
  • The mismatch is YAML-valid (the docs site renders it); it fails only Zod validation in the keystone. So it is a conformance gap, not a runtime break.

Options considered

  1. Relax the schema — allow a leading enum value with an optional parenthetical note (parse the enum prefix, keep the prose as a captured note). Lowest data churn; keeps the rationale inline where authors already write it.
  2. Split the fieldreversibility becomes a strict enum + a new optional reversibility_rationale (or reuse rationale) field. Cleanest for the graph/queries; requires migrating 9 records.
  3. Normalize the data — strip the parentheticals from reversibility and move the prose into the body (e.g. the Rationale/Consequences sections). Keeps the schema strict and unchanged; risks losing the at-a-glance "why" unless the body captures it.

Decision

Option 3 — normalize the data (resolved 2026-06-19, commit 6b1d662). The reversibility frontmatter field is a strict, machine-comparable door classifier carrying the door value only (one-way door / two-way door, or the bare one-way / two-way). The captured nuance — which internals are reversible, the durable commitment, mixed-door reasoning — moves into the body as a **Reversibility:** <door> — <why> line, the single-source-of-truth home for the "why". For a mixed-door record the value is the dominant / harder-to-reverse door and the body line states both sides. Applied across 40 decision records; the schema doc-comment in packages/okf/src/schema.ts was updated to state the strict rule.

Rationale

Option 3 keeps the keystone parser's z.enum the single enforced standard (Extraction runtime architecture — the moat) and keeps the field a clean classifier for queries ("show me every one-way door") and for the JSON Schema handed to the extraction tool — while still preserving the captured why by relocating it to the body, which the model already treats as the home for tacit rationale (Dossier — The Knowledge Model (v0) principle 7). It was preferred over Option 1 (relax the schema), which would have weakened the classifier and let prose drift back in, and Option 2 (split the field), which adds a second field to every record for nuance the body already carries. The cost — one-time churn across ~40 immutable-id records — was acceptable and one-way bounded, and ids were untouched (only field value + a body line changed).

Consequences

  • All decision atoms now pass @dossier/okf validate; pnpm kb:check reports the KB clean (139 atoms / 147 node ids, 0 load errors). This unblocks a CI parse/validate gate over knowledge/** (the reversibility prose drift was its largest blocker).
  • The body **Reversibility:** line is now the authoring convention for new ADRs — door value in frontmatter, nuance in the body. New records should follow it rather than re-introducing prose into the field.
  • The runtime-impact close-out (persona-grounding load errors that the prose form caused) is tracked separately in Fix the 41 KB load errors degrading Phase-0 persona grounding (dangling persona-grounding targets); the reversibility class is resolved by this decision.

Review

Verified by pnpm kb:check (clean parse over knowledge/**, 0 load errors) and the post-sweep scripts/agency-phase0-dogfood.mjs run after 6b1d662. Revisit only if a later need (e.g. richer mixed-door modelling) argues for re-opening as Option 2 (split-field) — a two-way door.