Skip to content

[epic·design] How we ask, how we collect, how we distill — one view over the question layer #398

Description

@atomchung

Umbrella for the product-experience half of the 2026-07-25 review. #395 and #396 are the two concrete pieces; this issue holds the frame they answer to, and the owner constraint that reshapes both.

The owner constraint (2026-07-25) — options over typing

Prefer options. Do not make the user type. The cost of typing is high enough that a free-text field is a worse question even when it captures a better answer. Lightweight interaction is the binding constraint, not a preference.

This does not conflict with #395's shift from backward motive to forward condition. It changes how that condition is captured:

The options can be concrete conditions the engine generates from this user's own numbers — not abstract categories.

Today (abstract, uncheckable):

Why did you buy NVDA?
  A. I had a planned thesis      B. I chased the momentum
  C. Someone recommended it      D. No clear thesis

Proposed (concrete, mechanically checkable, still one click):

What would make you sell NVDA?
  A. It falls back to $150 (your cost basis)
  B. It passes 40% of the portfolio (32% today)
  C. Quarterly revenue growth drops under 30%
  D. Haven't thought about it

Every option is generated from this user's actual position, so every one is a condition the next review can reconcile mechanically. The click cost is identical to today's. What changes is that the stored answer means something a quarter later.

Two properties worth naming: the option set is itself teaching — a user who has never written a falsifiable condition sees four examples drawn from their own portfolio. And "haven't thought about it" stays a first-class answer, not a hidden skip; it is often the most diagnostic one.

The three questions this epic holds

1. How do we ask?#395. Forward conditions instead of backward motives, because a backward motive is contaminated by memory decay, hindsight bias, and self-serving attribution. Now constrained to option form per above.

2. How do we collect?#396. Dynamically generated options break an assumption the delivery contract was built on: answers.json stores one canonical value per question, but a generated option has no stable enum behind it. ux_receipt's surface_digest can still prove the options were presented verbatim (good — that mechanism survives), but what gets written needs a design. Also unresolved: whether an "Other / let me say it myself" escape hatch exists at all, given the constraint above.

3. How do we distill a decision from the answers? — not yet opened. Given a stored condition ("sells if it passes 40% of the portfolio"), the next review must decide: did it trigger, did the user act, and what does the gap mean? The engine already has the machinery for the mechanical half (problems.py, the 30/60/90 due_revisit checkpoints). The judgment half — what a broken condition means, and when it is worth saying — is undesigned. This is where #54's rationalization concern resurfaces: a user who broke their own stated condition will have a reason ready.

What is decided

What is not decided

The problem none of this solves

Ostrich effect: investors check portfolios 9.5% less after market declines (Karlsson, Loewenstein & Seppi 2009; Sicherman, Loewenstein, Seppi & Utkus). The review is most valuable exactly when the user is least likely to open it.

Better questions do not make someone show up during a drawdown. This is a plausible primary cause of why trading journals fail in practice, and it sits upstream of everything above. Not folded in here because it is a different layer — product cadence, not question design.

Pieces

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions