The bluebook surface is itself declared, in syntax.bluebook — which
means the surface can carry its own lifecycle the same way any other
word in this language does: proposed, admitted, deprecated,
retired.
A proposed or retired word reaches no projected parser table. To a
projected reader — the generated Rust parser, the DSL reference, the
keyword table any tool builds from Syntax — that word does not exist
yet, or does not exist any more. There is no separate “is this word
still supported” question to answer by hand; the language’s own
declaration already answers it.
A renamed word keeps its old spelling in was: — read straight off
the language’s own live grammar table, the same one every builder’s
word-admission check reads:
table = Hecks::Bluebook::MetaValidator::SyntaxBoot.call
read_model_row = table[:keywords].find { |row| row[:context] == "Bluebook" && row[:word] == "read_model" }
read_model_row[:was] # => "report"
That was: is what lets era text minted back when report was still
the word keep parsing today, under the same shadow-parsing bridge
MetaValidator.shadow_parsing? gates for every renamed word
(EraGuard.shadow_parse runs it at boot, at mint, and during tamper
detection): live source refuses the old spelling outright, and frozen
era text still gets it.
```ruby bluebook Hecks.bluebook “LanguageVersioningDemo” do vision “One aggregate and one read model, to watch a renamed word’s two fates.”
aggregate “Ticket” do attribute :code, Code identified_by :code value_object(“Code”) { attribute :value, String }
command "Open" do
sets :code
emits "TicketOpened"
end end
Hecks::Bluebook::MetaValidator.while_shadow_parsing do report “TicketList” do reference_to Ticket include Ticket end end end
Live source gets no such bridge — the same `report` call, outside
`while_shadow_parsing`, names its own replacement instead of running:
```ruby
Hecks.bluebook("LanguageVersioningLiveAttempt") { report("Nope") { } } # ~> Malformed: report is gone
Not every renamed word takes this two-tier shape — then_set, sets’s
own predecessor, instead keeps a dedicated status: "deprecated" row
of its own rather than living only as sets’s was: (see
CommandBuilder#then_set_impl’s own comment for why); either shape
answers “does this still parse” from the language’s own declaration,
never from a maintained changelog.
hecks language_run.propose and its siblings walk a language change through the stations a rename or
a new word actually needs: snapshot the current state, rewrite the
corpus to the new spelling, regenerate every projected table (parser,
reference, vocabulary), gate on the full suite, and restore the
snapshot on red rather than leaving the tree half-migrated.
This is the same discipline PostgresEra applies to a domain’s own
vocabulary (see Schema evolution), turned on the
language that hosts every domain: a word can change without every
bluebook that already used the old spelling breaking, and the record
of what changed and why lives in the language’s own declaration, not
in a changelog someone has to remember to update.