v1.15.0
Roadmap Tranche 6 resolved (2026-07-12): Gate G2 closed with residual area failures = 0/8
on the calibrated baseline (docs/research/2026-07-g2-verdict.md) — the T6 area-syntax sugar
is parked behind frozen reversal triggers, and only the tranche's unconditional Track B
items ship below.
Added
matchVocabulary— one shared closed-vocabulary matcher, and the advisoryW_ALIAS_MATCH.
The token-bounded matcher core (normalizeLabel/synonymMatchesLabel) moved from
src/intent-concepts.tsinto newsrc/vocabulary.ts, and the scattered room-label regexes in
analyze.ts/analyze/circulation.tsare re-expressed as its data-drivenUSE_VOCABULARY
(canonical vs alias words per use kind). One matcher core, two vocabularies at two layers — the
brief-levelCONCEPTStable andSYNONYMS_VERSIONare untouched (judge fixture byte-green; no
second concept table). New advisoryW_ALIAS_MATCHfires when a room with no authored
usesclassifies only via an indirect alias ("Powder" → WC, "Foyer" → entry), carrying a
machine-applicable fix that inserts the explicituses …; corpus classification is pinned
byte-identical bytest/vocabulary-equivalence.test.tsover every example and eval golden.rankFixes— deterministic cost ordering for a diagnostic's fix alternatives (exported).
Orders the mutually-exclusivefixeson one diagnostic by applicability rank → total edit
magnitude (smallest change wins) → earliest offset → stable index.arch fixnow applies only
the top-ranked alternative per diagnostic; LSP code actions present alternatives in the same
canonical order. Identity on today's singleton arrays, so existing behavior is byte-identical.describe().freedom— a degrees-of-freedom placement report (append-only). Per placed
element, whether its position was authored absolutely or derived by the resolver — rooms
absolute/relational/strip, openingsattached/absolute, furniture
anchored/against-wall/absolute— as per-family counts plus oneelementsrow each.
Facts only (ADR 0005); the internal marker never reaches the Scene, so rendered output is
unchanged.- Optional metric unit suffixes on numeric literals (roadmap Tranche 6 Track B). A number may
carry amm/cm/msuffix, folded to millimetres at lex time:3m→3000,3.5m→3500,
3cm→30,3mm→3(an explicit no-op). Bare numbers still mean millimetres, so every
existing plan's output is byte-identical (a determinism/byte-equality test compiles a suffixed
plan and its bare-mm twin and asserts equal SVG). The conversion is exact — decimal-point
shifting on the digit string, never a floating-point multiply — so3.333mis exactly3333and
0.0005mis exactly0.5mm. The suffix must sit immediately after the digits (no space) and
does not fire when a letter follows (3meters= number3+ identmeters); each component of a
WxHliteral may carry its own suffix (3mx4m,3.5mx4200). Deliberately no area unit
(m²) — that belongs to the parked T6 area syntax (Gate G2 closed; see
docs/research/2026-07-g2-verdict.md). The formatter normalises a suffixed literal to its mm
value (3.5m→3500). Folded in the lexer (src/lexer.ts); the grammar source of truth
(src/grammar/tokens.ts) and every generated artifact — editor grammars,grammars/archlang.gbnf,
spec.llm.md,llms-full.txt— carry the optional suffix. - Note (eval baseline):
spec.llm.mdis the eval's author prompt, and this change adds a line
to it, so it now differs from the prompt behind the 2026-07-11/12 calibrated live baseline. No
scoring/judge/fixture code changed; re-running the paid live baseline under the new prompt stays a
separate, owner-approved action (default: not run).
Changed
arch fixnow collects fixes from lint diagnostics too (previously compile-stage
diagnostics only).W_ALIAS_MATCHis the first lint rule to carry a fix; the L1 gate's
l1Pipelineremains the compile-stage-fix +repairreference pipeline and is unaffected.- A room labelled with a WC-only alias (e.g. "Powder") now classifies as a WC. The word was
dead in the old regex cascade (WC_REwas only consulted afterWET_RE, which never matched
it); the vocabulary form resolves it, flagged byW_ALIAS_MATCH. The one deliberate
reclassification — every other label classifies exactly as before (pinned by test).