Summary
There are currently two spellings of "derived read shape": object.projection (+ origin.*, the SQL/read-model path) and object.value (+ origin.*, used for FR-004 prompt/template payloads). FR-024 §1 states outright that these arose "by accident of which feature shipped them," migrated one (entity+extends+view), and spared the other. The value spelling is a grandfathered compatibility spelling, not a principled category — and it leaves a permanent "why are there two?" seam every adopter re-asks.
The principled boundary (direction of data flow)
- Projection = system-PRODUCED output. Derived from the entity graph, read-only at the subtype level, optionally addressable (borrowed identity ⇒ get-by-id) and/or materialized, referenced as an operation's
outputRef.
- Value = caller-CONSTRUCTED input / embedded shape. Command inputs, proc args (
@parameterRef), embedded VOs whose storage belongs to the owning entity's field. Never populated, never sourced, never keyed; content equality.
A payload the framework assembles from Author.name + count(posts) + a nested collection is system-produced derived output — a projection by every test above. Calling its assembly "construction" stretches the population doctrine past usefulness (templates-and-payloads.md notes the payload codegen path is already shared with the projection path).
Proposal (pre-1.0, within ADR-0035's window)
- Retire
origin.* on object.value.
- Let
template.* @payloadRef accept sourceless projections.
- Nested payload shapes become sourceless projections reached by
origin.collection.
Then value purity becomes total — no identity, no source, no origins — so the value rule regime is trivially checkable (child-licensing, not conditional rules), and the ecosystem has exactly one spelling of "derived read shape."
Cost / benefit
Payload-VO codegen paths + conformance fixtures churn across 5 ports — but mostly node-type relabeling, since the payload path already shares the projection codegen path. Benefit: the projection/value boundary stops being a recurring question, and "value" becomes a clean, total-purity category. If the churn is declined, the fallback rule of thumb ("origins on a value are legal only inside template-payload assembly; any top-level, independently addressable derived read shape is a projection") leaves the seam permanently.
Summary
There are currently two spellings of "derived read shape":
object.projection(+origin.*, the SQL/read-model path) andobject.value(+origin.*, used for FR-004 prompt/template payloads). FR-024 §1 states outright that these arose "by accident of which feature shipped them," migrated one (entity+extends+view), and spared the other. The value spelling is a grandfathered compatibility spelling, not a principled category — and it leaves a permanent "why are there two?" seam every adopter re-asks.The principled boundary (direction of data flow)
outputRef.@parameterRef), embedded VOs whose storage belongs to the owning entity's field. Never populated, never sourced, never keyed; content equality.A payload the framework assembles from
Author.name+count(posts)+ a nested collection is system-produced derived output — a projection by every test above. Calling its assembly "construction" stretches the population doctrine past usefulness (templates-and-payloads.mdnotes the payload codegen path is already shared with the projection path).Proposal (pre-1.0, within ADR-0035's window)
origin.*onobject.value.template.* @payloadRefaccept sourceless projections.origin.collection.Then value purity becomes total — no identity, no source, no origins — so the value rule regime is trivially checkable (child-licensing, not conditional rules), and the ecosystem has exactly one spelling of "derived read shape."
Cost / benefit
Payload-VO codegen paths + conformance fixtures churn across 5 ports — but mostly node-type relabeling, since the payload path already shares the projection codegen path. Benefit: the projection/value boundary stops being a recurring question, and "value" becomes a clean, total-purity category. If the churn is declined, the fallback rule of thumb ("origins on a value are legal only inside template-payload assembly; any top-level, independently addressable derived read shape is a projection") leaves the seam permanently.