Skip to content

D356 — Invalid pages are repairable

Decision. The validation errors of a page (no frontmatter, unparseable frontmatter, no type, deeper than three segments) are lint checks, so kb_repair, the heartbeat, kb_review and the doctor see them. Where the answer is unique they carry a deterministic fix: add_frontmatter and missing_type use the type every other typed page of the map already shares (at least two, all equal), quote_value double-quotes the one line that breaks the block. Repairs write through kb.RepairConcept, whose validity rule is "the errors after are a subset of the errors before", so an unrelated fix is no longer blocked by a page's missing type. Two warnings join them: nonslug_file_name (fix: move to the slugified ID, through concept_move's code path) and empty_concept (no fix).

Why. A KB in bad shape could not be repaired at all: every repair went through the validated write path, and the validation errors themselves had no repair, so three kb_repair rounds applied zero fixes on such pages. RepairConcept is the alternative to "fix validity first, then everything else", which blocks every other fix on any page whose type cannot be resolved. The cost is a second write path with a weaker rule.

Alternatives rejected. - Most common type in the map: a majority is a guess, and a wrong type silently changes contracts. - Relax WriteConcept for everyone: agent writes must keep full validation. - Drop the mirrored lint errors and keep validate alone: the repair and the doctor never read validate. - Fix concept_too_deep by moving: where a page belongs is judgement. - Delete an empty page: no automatic deletion, ever.

Consequences. RepairConcept is used only by kb_repair, the heartbeat and repair-on-write, never by an agent-facing write tool (a test pins that concept_write still rejects an invalid concept). A repair never widens the error set (a test). No invented content: only derived values (an H1, a file stem, a type every sibling uses). gate_check lists a validation error once: the three lint checks that mirror validate are dropped when the same path is already in validation_errors. The four fixes are auto_repair defaults; nonslug_file_name runs in stage 2 of the heartbeat (D355) because it touches other files.