The most load-bearing screen in onboarding today is sixteen aspirational picks made before the user knows anything, and it is silently skippable. Same data, asked after they have said something real about a room.
Stay on budget
Keep costs predictable and avoid overspending.
Low upkeep & durability
Materials and systems that last and rarely need attention.
Energy efficiency & low bills
Lower monthly energy use and operating cost.
Energy independence & backup
Stay powered and self-reliant.
Aging in place & accessibility
A home that keeps working as needs change with age.
Health, comfort & clean water/air
A comfortable, healthy indoor environment.
Resale value
Choices that protect long-term property value.
Future-proofing & flexibility
Room to adapt, expand, and reconfigure later.
eight more below
answer_id is already there. Every line cites what they said.Aging in place
Must haveYou said you hate bending into cabinets, and you wanted that to hold outside the kitchen too. That's the one nobody volunteers on a list.
Fits our daily life
The kids do homework at the island while you cook. You want to face the room, not the wall.
Stay on budget
You measured six feet of counter in daily use. That is the length the island gets priced against.
I have nothing to go on for these. Add any that belong, or leave them and I will work it out as we go.
Aging in place
You said you hate bending into cabinets.
Fits our daily life
Stay on budget
Changing this is cheap
It updates the 21 decisions still open. Anything you have already decided stays put, and anything you set by hand stays yours.
Take one off and I stop guessing at it. I won't put it back on my own.
Aging in place
Fits our daily life
Stay on budget
Energy efficiency & low bills
You added this. I had nothing to go on.
You said grout is a nightmare to keep clean.
That sounds like low upkeep matters. Add it?
One line when a room turns something up. Never this whole screen again.
This section describes the system being replaced — the Flutter app under legacy/, still deployed. Its table, route and function names are legacy names and do not appear in the rebuild. Everything under What frame B changes is the rebuild.
Frame A is the most load-bearing screen in the current flow. Those sixteen tiles write project_vision_values, which pre-selects up to three strategy_priorities on a seeded decision wherever a priority crosswalks to a ranked value, and which powers the vision gate, the revisit digest, the vision digest and the Journey card.
It is also silently skippable. Select nothing, tap Continue, and no PUT fires at all. Every decision then ships with zero pre-selected priorities and the user is never told. The most consequential input in onboarding has no floor.
And there is no back button anywhere in post-creation onboarding (onBack: null), so those picks are unrevisable the moment you advance.
rank, same deal-breaker flag, same replace-set write — ReplaceVisionValues deletes the project's set and re-inserts it whole (postgres.go:3376). What moved is the naming: the rebuild's table is vision_values, a value is its label rather than a value_key, the flag is spelled is_dealbreaker, and the route is PUT /projects/{p}/vision (vision.go:37) — not the legacy /api one. And the table carries answer_id (0001_init.sql:1511), a nullable pointer to the answer a value was drawn from. That column is the evidence line, already in the schema and waiting for this screen. An earlier revision of this bullet said the model does not change at all and named value_key, is_deal_breaker and PUT /api/projects/:id/vision; none of the three exists anywhere in the rebuild.Legacy again, and this is the one place where that changes what has to be built. reseedProjectVisionPriorities, strategy_priorities and hand_set have no equivalent in the rebuild — zero occurrences across packages/, services/ and apps/. The four guarantees below are what frames C and D promise the homeowner out loud. Nothing implements them yet, and that is Q103's to settle, not this page's.
In the legacy app the backend already makes editing safe, which is why frames C and D need no modals or confirmations. reseedProjectVisionPriorities does four things that matter here:
hand_set rows. If you adjusted a priority on one decision by hand, a vision edit never stomps it. That is what lets the coach say "take one off and I stop guessing at it."So the honest answer to "what if it is wrong" is: change it, and the blast radius is exactly the open decisions you have not touched. Frame C says that out loud rather than making the user guess, and it names the real number: twenty-one open across the nine spaces, per _ds/FICTION.md. An earlier revision said fourteen, which matched nothing.
That answer is honest about the legacy app. It is a promise about the rebuild, and the four guarantees it rests on are the work — not a property the screen inherits by being drawn.
A derived value carries its evidence. A value you add carries "you added this, I had nothing to go on." Those are different claims and the UI should not blur them. It is the same rule as the extractor declining to record a vague word. It also means the "not heard yet" list is a real statement about our ignorance, not a leftover.
The kitchen is one room of nine. The primary bath will turn up something the kitchen could not, and so will the garage. The answer is not to re-show this screen. A new signal surfaces as one line at the end of that room's conversation, "you said grout is a nightmare to keep clean, that sounds like low upkeep, add it?", with a yes and a no. Frame D shows it.
Once you have answered that once, for that value, it does not come back. Combined with the hand_set protection, the rule is simple: the coach guesses until you touch something, then it stops guessing at that thing.
The first batch of decisions seeds unopinionated, because vision now arrives after the first conversation rather than before it. I think that is fine: nobody sees ranked options until after their first conversation anyway, and today's alternative is a set of priorities picked blind, which produces confident ranking on a bad signal.
If that is wrong, the fallback is three values in onboarding, not a return to sixteen. Ask for the deal-breakers only, and let the rest derive.
.tile is frame A's sixteen-up picker, .rank is the ordinal dot and .why is the evidence line under a derived priority. None of them exists in _ds/hc.css. The three that also used to sit here did nothing but shave .card, .callout and .section-header back below the shared rhythm, and they are gone. All four frames now run past the bottom of the phone, which is correct.