A persona engine that only does Person is a Person feature wearing the costume of an abstraction. The whole bet behind making coherence a descriptor-driven stage was that a second entity would be nearly free. Address was the test, and it is where the first session closes.
The second instance was nearly free
Address coherence means City, State, PostalCode, and Country agree. It reuses the exact detection and activation machinery from Person: a second descriptor that claims the existing address generators from the catalog, gated by the same corroboration-count activation. The only structural difference is that Address has no name anchor (there is no "FirstName of an address"), so its activation gate is pure corroboration count rather than anchor-plus-count. One genuine difference, and the framework absorbed it. That is the signal an abstraction is real.
One honest difference: how the bundle draws
The interesting part is where Person and Address diverge, because it taught me what the descriptor actually abstracts.
Person: correlated draws. Draw a gender, then a name that matches it, then ...
Address: row-projection. You CANNOT synthesize a coherent address field by field
(a random City plus a random State plus a random ZIP is nonsense).
So draw ONE real (country, state, city, postal, lat, lng) tuple, and let
the facets project from that row. Street and countryCode derive.
A descriptor does not just list facets. It owns "how to draw the bundle." For Person that is a sequence of correlated draws; for Address it is a single row lookup; the facets project either way. Same stage, same activation, two completely different generation strategies behind one abstraction.
A set of entities, not one persona
Generalizing also forced a small reframe. One object can host a Person and an Address at the same time, so the activation pre-pass resolves a set of entities per object, each drawing in registration order. Nested entities fall out of object-scoping for free: a nested Address is its own scope and coheres on its
own. (Two addresses flat on one object is still the deferred two-people case.)
Where the data comes from
Filling the address row table is a brief-shaped decision. Consistent with owning the rigor lane, core ships a small set of curated, real en tuples, where coherence is guaranteed because the data is real. Breadth comes through data packs, not core, and synthesis is used only where ground truth is impractical (street
numbers are always synthesized). Rigor in core, breadth at the edges.
Where composition and coherence meet
The last thing I checked was whether the two big v1.1 threads collide. Mostly they do not: composition substitutes complex types, coherence binds scalars, disjoint kinds, and the resolver pipeline I pre-paid for is coherence's host. The one genuine fork is a decomposition discontinuity: because coherence is object-scoped,
moving a facet into a nested object changes whether it coheres with its old siblings. I kept strict object-scoping as the v1.1 default (predictable and explainable) and reserved an explicit Inline operator to ship later alongside cross-entity correlation. Automatic reach-down lost, because cross-boundary magic is exactly the kind of thing that cannot be explained.
Takeaway
An abstraction earns its keep when the second instance is nearly free and the third is obvious. And when two systems meet, prefer the boundary you can explain over the convenience you cannot. That single rule, local and diagnosable over non-local and silent, turned out to be the spine of nearly every decision in this
series.
Where this leaves the first session
Coherence is worked through its load-bearing core and stays open on purpose: Company and temporal entities, cross-entity correlation (the person who lives at the address), and the catalog and dataset work all still have surface left. None of it is built. It is design, made deliberately and held revisitable, which is exactly where I want a library that intends to be the rigorous one to start.
Thanks for reading along this first pass. The whole point of building in public is that the reasoning is the product as much as the code is.
Top comments (0)