Description
We need a first-class answer type for any question the system can be asked. The simplest form is aspect — a three-valued atom from {:falsey, :truthy, :unknowny} — that honestly carries epistemic state alongside answer.
The -y suffix matters. It signals "leaning toward" rather than "is" — humble about what's actually known, especially in distributed/choreography contexts where the answer depends on what data has propagated and which parties have weighed in.
Three first-class values:
:truthy — the answer is yes, with whatever confidence the underlying machinery offers
:falsey — the answer is no, with the same kind of confidence
:unknowny — we don't have enough information to say, or sources conflict — surfaced honestly rather than collapsed to a default
Key properties:
- Surfaces uncertainty and conflict as data, not as nil or false. "I don't know" and "no" are different answers. So is "the data sources disagree."
- Lossy collapse from richer worlds. A richer answer (an Outstanding expectation with full detail; a value-metric option with multiple dimensions; a feasibility result with cost/distance/headroom) can collapse down to an aspect when the consumer only wants the yes/no/unsure. Same data, simpler projection — the IEEE 1164 collapse pattern at the answer-shape level.
- May carry data the answer is in relation to.
:truthy + the option that satisfies; :falsey + the reason; :unknowny + what's missing to resolve. The aspect is the headline; the data is the supporting story.
- Conflict resolution when we can. If sources disagree, the framework tries to reconcile — recency, authority, voting, ledger position. When it can't, it returns
:unknowny with the conflict surface.
- Honest surfacing when we can't. Don't manufacture certainty by picking one source arbitrarily.
:unknowny is the truthful answer, and the consumer can decide what to do with it (defer, ask more parties, escalate, fall back).
Why it matters
Most software collapses these three answers into two — :truthy and "everything else" — which silently hides the difference between "no" and "I don't know" and "people disagree." That hiding is where wrong decisions come from: the consumer thinks they got a :falsey when they actually got an :unknowny, and they act as if the question is settled.
For the choreography we've been yarning about — feasibility, qualification, alignment, value, taking-one-for-the-team — :unknowny is the most important of the three answers, because the whole machinery has to handle "we haven't aligned yet" gracefully. A party that gets back :unknowny knows to yarn further. A party that gets back :falsey knows to stop.
It also closes the IEEE 1164 loop at the answer-shape level. We've been yarning about projections and collapse across values (#169), worlds (the Provider / Assigner / Extended layering), and time (snapshot vs live). Aspect is the same shape applied to answers — the simplest projection any answer can collapse to, with the option to carry richer detail when the consumer can use it.
What we'd find useful
- A typed answer shape — an
Aspect (or Answer?) type carrying {:falsey | :truthy | :unknowny, data_or_nil}.
- Conventional functions for asking the simple form (
is_feasible?(shelf, customer) returns :truthy / :falsey / :unknowny) and the richer form (feasibility(shelf, customer) returns the same plus the data the answer is in relation to).
- Conflict-resolution hooks — when multiple sources contribute, how does the framework reconcile, and when does it surface
:unknowny?
- A documented collapse from richer answer types (value metrics, expectations, qualification results) down to aspect, so consumers at the simpler level can still ask and get an honest answer.
A possible direction
Feasibility from #38 and #39 should adopt the aspect shape natively:
# simple form
Access.is_serviceable?(customer_location)
# => :truthy
# richer form — same answer, with the options
Access.serviceability(customer_location)
# => {:truthy, [%{shelf: ..., technology: :adsl2plus, distance_m: 800}, ...]}
# unknowny form — sources conflict or data is missing
Access.serviceability(customer_location_with_disputed_address)
# => {:unknowny, %{conflict: [...], missing: [:wireline_inventory_freshness]}}
Same for installer availability (#39), value metrics (#40), and the persistent expectations of #3 — every answer in the system should be expressible as an aspect, with the option to carry detail when asked.
The exemplar work: pick one feasibility question (probably from #38 since it's the simplest), express its answer as Aspect, exercise all three values including a conflict scenario that returns :unknowny, and let the shape settle. Then propagate.
Related:
- #3, #38, #39, #40 — the questions whose answers need this shape.
- Upstream reasoning/valuing framework — likely already has its own opinion on the answer type; this is the substrate that lands.
Description
We need a first-class answer type for any question the system can be asked. The simplest form is
aspect— a three-valued atom from{:falsey, :truthy, :unknowny}— that honestly carries epistemic state alongside answer.The
-ysuffix matters. It signals "leaning toward" rather than "is" — humble about what's actually known, especially in distributed/choreography contexts where the answer depends on what data has propagated and which parties have weighed in.Three first-class values:
:truthy— the answer is yes, with whatever confidence the underlying machinery offers:falsey— the answer is no, with the same kind of confidence:unknowny— we don't have enough information to say, or sources conflict — surfaced honestly rather than collapsed to a defaultKey properties:
:truthy+ the option that satisfies;:falsey+ the reason;:unknowny+ what's missing to resolve. The aspect is the headline; the data is the supporting story.:unknownywith the conflict surface.:unknownyis the truthful answer, and the consumer can decide what to do with it (defer, ask more parties, escalate, fall back).Why it matters
Most software collapses these three answers into two —
:truthyand "everything else" — which silently hides the difference between "no" and "I don't know" and "people disagree." That hiding is where wrong decisions come from: the consumer thinks they got a:falseywhen they actually got an:unknowny, and they act as if the question is settled.For the choreography we've been yarning about — feasibility, qualification, alignment, value, taking-one-for-the-team —
:unknownyis the most important of the three answers, because the whole machinery has to handle "we haven't aligned yet" gracefully. A party that gets back:unknownyknows to yarn further. A party that gets back:falseyknows to stop.It also closes the IEEE 1164 loop at the answer-shape level. We've been yarning about projections and collapse across values (#169), worlds (the Provider / Assigner / Extended layering), and time (snapshot vs live). Aspect is the same shape applied to answers — the simplest projection any answer can collapse to, with the option to carry richer detail when the consumer can use it.
What we'd find useful
Aspect(orAnswer?) type carrying{:falsey | :truthy | :unknowny, data_or_nil}.is_feasible?(shelf, customer)returns:truthy/:falsey/:unknowny) and the richer form (feasibility(shelf, customer)returns the same plus the data the answer is in relation to).:unknowny?A possible direction
Feasibility from #38 and #39 should adopt the aspect shape natively:
Same for installer availability (#39), value metrics (#40), and the persistent expectations of #3 — every answer in the system should be expressible as an aspect, with the option to carry detail when asked.
The exemplar work: pick one feasibility question (probably from #38 since it's the simplest), express its answer as
Aspect, exercise all three values including a conflict scenario that returns:unknowny, and let the shape settle. Then propagate.Related: