Skip to content

BUG: Onboarding profile step is multiple-choice only — no free-text entry for name #245

Description

@jeonghun-jj-lee

Important

Problem

During first-run onboarding, the overture's free-form identity ask (name, affiliation) can only render as a choice card: the engine forces every interview question through the question tool, whose only text path hides behind a "Type your own answer" pseudo-option. A new user cannot simply type their name — the symptom in this intake filing.

Approach

Give the question card an explicit free-text shape — a text card (a question with kind: "text" in the schema): a free-form question renders a bare text input with submit, the interview contract teaches the model to use it, and the prose guard's nudge learns both question shapes. Key reason: it preserves the one-ask-mechanism contract (the stall fix that forces prose questions into cards) while making free-form asks first-class instead of routing them through an option list.

Approaches Considered

  • Text-mode card (chosen) — one schema field + a renderer branch; fixes every free-form ask at once and keeps the card the single ask mechanism.
  • Prose carve-out for free-form questions — rejected: re-admits the interview-stall class the prose guard was built to close, and prose answers bypass the question-answer plumbing.
  • Implicit empty-options signal (zero options renders a text input) — rejected: magic, fragile against renderer changes, and undiscoverable to the model.
  • Wizard-only identity (chat never asks the name) — rejected: fixes the name step only, couples the chat flow to a dismissable modal, and leaves every other free-form ask broken.

Scope

In: the question schema in both schema packages (new optional kind, defaulting to choice); the three question renderers (app dock, TUI, CLI) branching a text-card shape; the app dock honoring the typed-custom-answer flag for choice cards (today it appends the pseudo-option unconditionally); the prose guard's nudge text (bilingual: choice vs free-form); the question-tool description; the interview-contract text in the extension's score compiler and the overture + pulse-designer score bodies; a fork ADR recording the decision; the engine pin bump with the extension re-vendoring and its contract changes riding the same release.
Out: wizard ↔ overture unification (works today, deduped by the routing predicate — parked as a separate thread) · choice-question rendering (unchanged) · score-frontmatter changes (the presence/absence of choices already marks a question free-form).

Assumptions / Open Qs

Assumes the existing typed-custom-answer resolution path accepts a text-card submission unchanged (no new answer plumbing). No open questions.


Acceptance Criteria

  1. Repro passes: with a fresh profile (no stored identity, no profile card, no onboarding-completion marker), a new chat's identity ask renders a text card — bare input with submit, no option list, no pseudo-option — and submitting a name resolves the ask and records it.
  2. Schema: a question payload with the text kind decodes in both schema packages; a payload without a kind decodes as a choice question (back-compat); an unknown kind value fails decoding loudly rather than silently degrading to choice.
  3. Renderers: the text kind renders no option rows and no pseudo-option in the app dock, the TUI, and the CLI; a choice question renders its options, and the dock shows the typed-custom-answer row only when the question allows it.
  4. Guard: a prose question in an active interview still triggers the nudge, whose text now instructs options-with-recommended-first for choice questions and the text kind for free-form questions; a turn that called the question tool (either kind) never triggers it.
  5. Contract: the compiled session prompt for both the overture and the pulse-designer instructs free-form questions to use the question tool with the text kind; "free-form answers can be plain text" is gone from the contract text and both score bodies.
  6. Regression: the overture's choice questions (e.g. environment) still render as option cards with the typed-custom-answer row.

Key Decisions

  • One new optional question field, kind (choice default, text), added to the agent-facing and server question schemas; an absent kind decodes as choice, so existing payloads and sessions are unaffected.
  • The text card is the header plus a bare text input with submit; submit is enabled once the trimmed text is non-empty; dismissal/rejection semantics are unchanged.
  • Text-card answers resolve through the existing typed-custom-answer path — no new answer plumbing.
  • The prose guard's behavior is unchanged (prose questions in active interviews are still forced into cards); only its nudge text learns both shapes, and the model picks the shape from the question it is re-asking — no classification heuristics.
  • The contract change is uniform across all Amico interviews (overture and pulse-designer free-form parameters alike), keeping the rule statable in one sentence: every question is a card; choice questions list options; free-form questions take text.
  • Ships as the next engine pin; the extension re-vendors and its contract-text changes ride the same release.

Constraints & Invariants

  • Every user-facing interview question remains a card; no prose-question path is reintroduced.
  • The prose guard keeps firing on prose questions in active interviews, at most once per assistant message as today.
  • Choice-question rendering changes only in the dock's flag handling; no other visual or behavioral change.
  • No score-frontmatter schema changes; the choices split remains the only free-form marker.
Prior Art / Patterns
  • The prose-question guard in the engine fork's session turn loop (PR Δ3 — Run-dir → S3 incremental sidecar (keep amico-run thin) #37, 2026-07-20) — the interview-stall class it closed, and why a prose carve-out was rejected.
  • AMICODE-PATCHES.md patch 9 — the question card as the one ask mechanism; amicode_ask deprecated.
  • The onboarding modal's about-you step — free-text identity inputs that already work; deduped from the chat overture by the profile-identity routing predicate.
  • The TUI's typed-custom-answer flag check — the pattern the app dock should honor for choice cards.
  • Glossary: the fork's root CONTEXT.md gained Question / Choice Question / Free-form Question / Text card with this design.
  • ADR: fork docs/adr/ (next number) — "Free-form questions render as text cards," committed with this work.

Source

  • This issue's intake filing — preserved verbatim as a comment on this issue posted at maturation time (and condensed in the diagnostics block below); matured in place per the report-a-bug maturity contract; suggested_path: A re-checked at review → criteria 2–4 failed → Path B, matured through the design pipeline (brainstorming + grill-with-docs).
  • Durable record: the fork ADR and CONTEXT.md glossary entries named above.

Notes

  • Upstream re-check (fork-surface clause): the upstream repo was not visible from the filing auth; moot in any case — the prose guard is an amicode-only patch, so no upstream fix can exist for it, and the upstream question form has no free-text mode either.
  • The wizard ↔ overture duplication (two identity collectors, two stores, reconciled by the routing predicate) is parked as a separate design thread.
Intake diagnostics (condensed — the verbatim original is preserved in a comment on this issue)
  • extension: harmoniqs.amicode 0.2.0 · os: Darwin 25.5.0 arm64
  • engine: harmoniqs/opencode v1.18.10-amicode.1 (base 1.18.10)
  • Symptom: the onboarding profile step renders name/affiliation as multiple-choice only; entering a real name requires choosing "Other" and typing into the custom-answer box.
  • No active run; the symptom is in the onboarding UI flow, not a solve.

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions