Reconcile the decision reversibility field — free-text prose vs. the @dossier/okf enum
0017-reversibility-schema-conformance
- 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:
reversibilityis a strict door classifier in frontmatter; the captured nuance lives in a body**Reversibility:** <door> — <why>line. Conformed across 40 decision records + the@dossier/okfschema doc-comment in commit6b1d662;pnpm kb:checknow 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 strictz.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
- 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.
- Split the field —
reversibilitybecomes a strict enum + a new optionalreversibility_rationale(or reuserationale) field. Cleanest for the graph/queries; requires migrating 9 records. - Normalize the data — strip the parentheticals from
reversibilityand 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
decisionatoms now pass@dossier/okfvalidate;pnpm kb:checkreports the KB clean (139 atoms / 147 node ids, 0 load errors). This unblocks a CI parse/validate gate overknowledge/**(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.