Skip to main content

Retired diagnostic codes

Eleven spellings are retired. Numbers are never reused. If one spelling came to mean something else, past output and past logs would stop being readable. These keys are not in the ledger (DIAGNOSTIC_CODES), so a retired spelling stops the type checker — DIAGNOSTIC_CODES["BND07"] is a TS2551. To see the run-time value, widen the type first and you get undefined.

DIAGNOSTIC_CODES["BND04"]; // "error"

const ledger = DIAGNOSTIC_CODES as Record<string, "error" | "warning" | undefined>;
ledger["BND07"]; // undefined — retired

They were retired for three different reasons.

ReasonRetired numbers
They were judgements, so they moved to koyu validate — they carry thresholds and decide architecture, not the consistency of the compositionENV01 RUN06 RUN07 RUN08 SIT03 SIT05
They were all one story — "the information needed is missing" — so they folded into the SUF familyHGT03 HGT04 HGT05 RUN04
The job itself disappearedBND07

The list​

RetiredSeverity thenWhat it said thenWhat says it now
BND07warningThese touch, but no boundary is declaredNothing — an undeclared contact is a wall by default
ENV01warningA hole in the envelope — a stretch of perimeter facing nothingNothing — a face onto the outside is a wall by default, so the hole cannot arise. That nobody named the outside is BND08 (warning)
HGT03warningThe storey above has no slab, so the height check cannot runSUF03 (warning)
HGT04warningThe ceiling height is unknown, so the height check cannot runSUF01 (error)
HGT05warningA space with a region whose level cannot be determinedSUF02 (error)
RUN04warningNo level above, so the run's shape cannot be generatedSUF04 (warning)
RUN06warningThe derived steps are cramped (a narrow going, or 2R+T outside the comfortable band)koyu.schematic.stair.proportion (caution)
RUN07warningThe derived slope departs from the declaration or the usual bandkoyu.schematic.ramp.declared-slope / koyu.schematic.escalator.usual-slope (caution)
RUN08warningThe run has a shape but no vertical boundary connecting the storeyskoyu.schematic.run.disconnected (caution)
SIT03errorThe building escapes the site outlinekoyu.schematic.site.escape (violation)
SIT05warningThe declared site area and the derived one disagreekoyu.schematic.site.area (caution)

Every koyu.schematic.* name in the right-hand column is not a koyu check diagnostic but a koyu validate rule. They are different types: check returns Diagnostic { code, severity } and validate returns Finding { rule, level }. level is violation (not met) or caution (suspect), an axis of its own — it measures architectural weight, where severity measures how the composition is broken.

Why the judgements left the core​

check used to say two kinds of thing at once. "References an undefined space" (REF01) and "the stair is cramped" (RUN06) sat in one array with the same severity. The first is a failure of reading — the composition is broken. The second is a judgement — this is architecturally suspect.

Two problems forced the split.

First, green could not be defined in one sentence. Writing down what "check is green" meant produced: "the composition is not self-contradictory, except that the envelope, stairs, daylight and site are also judged architecturally, but roughly." That is not a definition. It can be said in one sentence now: the composition is self-consistent as data, and a single shape can be made from what is written. Nothing is claimed about architectural validity.

Second, every new judgement stretched the frozen surface. Every time compartmentation, escape distance, smoke extraction or an area ratio by occupancy wanted adding, the ledger of diagnostic codes grew — and all of it looked like surface that had been promised not to break. Judgements now live on their own surface, where adding or dropping one moves no language version.

Nothing was thrown away; it was moved. Run koyu validate and the corresponding rules still say the same things.

koyu validate examples/tower/main.muro --profile koyu.profile.schematic-screen --as-of 2026-08-03

Why sufficiency became one family​

HGT03, HGT04, HGT05 and RUN04 were split across the height and vertical-circulation families by name, but they said one thing: the information needed to make a shape is not written.

RetiredIts body thenWhat it was actually saying
HGT03The level above has no slab, so the height check with this storey cannot runA value the formula needs is not written
HGT04The ceiling height is unknown, so the height check cannot runThe same
HGT05Its level cannot be determinedThe z is not written
RUN04No level above, so no shape is generatedNot one shape comes out

None of them reports a broken invariant. Where HGT01 / HGT02 say the written values contradict each other, these four said the values are not written. Different family.

Two of them changed weight when they were folded in. HGT04 (warning) became SUF01 (error), and HGT05 (warning) became SUF02 (error). With no ceiling height there is no height to extrude; with no level there is no z. Either way not one solid comes out, which is not suspect — no shape can be made. Severity is an invariant property of a code, so a change of weight demands a new spelling. That is the other reason these four are retired numbers.

The height check now looks only at whether the written values contradict; when a value is absent it moves on in silence, and saying so is the sufficiency check's job.

BND07 alone has no replacement​

BND07 was once the warning "these touch, but no boundary is declared". Making a wall the default between two touching spaces ended its job. An undeclared contact no longer means "undefined" but "wall", and the declaration the warning was pressing for was replaced by the derivation itself.

So a boundary is written only to carry an exception (type:open, air:1) or to hang an attribute or an opening on it. Write nothing and a wall is derived.

And since a wall is impassable without a door, a building with not one door written is green and sealed. The instrument for looking at circulation is not check but koyu doors, and koyu validate's koyu.schematic.access.unreachable.

Back to the index​

The 65 live codes are on The diagnostic code index.