plan — everything a request settles before any syntax exists
A plan is the complete output set of one request, named before a token of the target language has been written.
The planning road moves through related views of one declared request. The account is what the caller walked in with: the kind-specific content bound to its exact captured declaration and owner-qualified kind, and the independent captures it declares it stands on. The intent is what that request meant — its owner-qualified kind over the content commitment, and nothing else, so two requests that meant the same thing derive one intent whatever machinery would realize them. The context is what the request is decided under: the profile it selected, and the generator answering. The plan is what all of that decides: every unit that will exist, where each came from, what invalidates the whole, why it was decided that way, and what it does not claim.
The output firewall
A plan states its complete membership up front, and the declared set is the whole set.
A rendering is proved against it seat by seat, so a unit nobody planned has nowhere to be admitted and a planned seat nobody rendered is a refusal rather than a quiet absence. The membership is structurally non-empty and bounded: a plan that would generate nothing is a disposition, and one that would generate past the declared magnitude refuses rather than materializing part of a set.
Two members may not stand under one seat. Closure matches a rendered unit to a planned one BY SEAT, so a doubled seat would make that match elect one member and prove nothing about the other — which is why the doubling is caught in the declaration rather than downstream.
One account, and no second copy
The intent, invalidation, diagnostic-cause, and origin readings all take the account.
None of them keeps a copy. A second list of what content depends on — beside a plan, inside a context, at a call site — would agree with the first until it did not, and nothing downstream could tell which of the two a plan was actually planned over.
What makes a plan stale
The watch set is derived from the account and the context rather than listed at a call site, and it covers all of both.
A set watching only part of a declaration’s causes is byte for byte the shape of a complete one, so a plan over it would read as current after an unwatched cause changed. Compiler-owned invalidation follows the identity-bearing facts the account and context already hold rather than restating them at the planning call. Consumer-owned invalidation names any further declared fact in the consumer’s own vocabulary. The compiler enumerates no further nouns there, because a mechanism profile, a work formula, and a fixture population are three different owners’ meanings and a roster of them would be this crate minting vocabulary for facts it does not hold.
What it does not do
It renders nothing, proves nothing, and explains nothing.
It holds no rendered bytes and therefore no digest of them: a member states the contract its eventual digest must satisfy, and closure recomputes that digest over the bytes a renderer actually produced. It names no delivery of its own either — a member’s delivery is its seat’s own answer, so two plans of one kind cannot disagree about which build compiles a seat’s unit. And it enumerates no kind: the owner-qualified name, canonical content, seats, and questions all arrive from whoever declared the kind.
How it says no
Planning issues are independent and co-establishable — one pass may find a doubled seat and an overrun magnitude at once — so a refusal carries every issue its pass established rather than electing a primary one.
A body that fills its bound keeps what fits and counts the rest, which is a different statement from “no further defects exist”.
The refusal is an ordinary error: it prints, it is a core::error::Error, and it projects into a diagnostic through the one contract every refusing step implements.