Skip to content

Remove the no-model demo path; make setup the single road to a real first conversation - #474

Merged
charneykaye merged 2 commits into
mainfrom
feat/single-road-first-run
Aug 22, 2026
Merged

Remove the no-model demo path; make setup the single road to a real first conversation#474
charneykaye merged 2 commits into
mainfrom
feat/single-road-first-run

Conversation

@charneykaye

Copy link
Copy Markdown
Contributor

Summary

The first conversation a new player has decides whether there is a second one — and its one job is to prove this is not a chatbot: the entity across the table has its own universe of concern, and the player succeeds by investigating it, appealing to it, and compelling within it. The no-model paths did the opposite. The fake runtime returns the same hard-coded reply on every turn, forever ("Hello there. I am a simulated NPC."), and the scripted tutorial is on rails. Offering either as first contact taught "this is a bad chatbot" at the exact moment of maximum skepticism — then lost the player for good.

This PR removes the entire no-model conversation offering from every user-facing surface and reinvests the first-run flow in getting the player to a real conversation. Closes #473.

What's removed

  • Welcome: the "Try it right now" scripted-tutorial card. One road now: Set me up (advanced Ollama/GGUF paths stay).
  • Installing: the "Have your first conversation [scripted]" CTA.
  • Choose / Model Manager: the "Continue without a model / Text-only demo" card; DemoConfirmStep and the demo-warning step are deleted.
  • Preflight / Settings health: the universal "Try text-only instead" escape hatch (a blocked machine gets a fix action, details, and copy-diagnostics — honest failure beats fake success).
  • Home: the "Try text-only demo" no-model card.
  • Conversation / Debrief: the SCRIPTED/DEMO badges, the mid-session model-ready toast machinery, and the "Try it with the real AI" upgrade CTA.
  • Flow internals: handleConfirmDemo, handleStartTutorial, the demo onboarding outcome write, and the tutorialComplete / tutorialInstallId / activeRuntimeHint localStorage keys (stale legacy values are inert).
  • e2e: P2 "instant play" journey deleted; the onboarding fast trio becomes P1/P7.

What replaces it

  • Welcome states the promise plainly: "Not a chatbot. Not a mirror." — everyone you talk to arrives mid-life, with stakes, moods, and goals that have nothing to do with you.
  • Installing turns the download wait into the recruitment window: the promise, the three-beat loop (investigate their universe → appeal and compel within it → succeed on their terms), and previews of real scenarios from the registry as "your first missions" (the internal tutorial scenario is never advertised). No playable facsimile.
  • Arrival: install completion lands the player in the scenario library, one click from a real first conversation.
  • All new/changed strings are localized (en + de).

Backstop (API-level guarantee)

POST /api/sessions now refuses (409, with a clear finish-setup message) any session that would resolve to the fake or scripted runtime unless the request pins that runtime explicitly — covering both a persisted model-free selection and the config-default fake shared runtime on a profile that never installed a model. Tests and dev tooling keep the explicit pin; a player can never fall through to a puppet by accident. The fake/scripted runtimes and the first_words_tutorial scenario remain as internal test/dev infrastructure.

Migration

A legacy profile with a recorded demo outcome no longer counts as having a model: GET /api/setup/status resolves incomplete (never never-run, so no wizard bounce), which shows the existing non-blocking finish-setup banner steering the user to install the real thing.

Verification

  • Frontend: 47 files / 1278 tests pass; tsc clean; eslint identical to main (no new issues); i18n audit clean.
  • Backend: 2047 passed / 3 pre-existing root-container preflight failures (identical on clean main); new tests cover the 409 backstop, the explicit-pin path, and the legacy-demo status migration.
  • e2e onboarding: 49 passed (P1/P3–P8) after P2 removal; actionlint clean on the workflow change.
  • Pushed tree verified byte-identical to the locally tested working tree (matching git tree SHA 64cff7df).

🤖 Generated with Claude Code

https://claude.ai/code/session_01C9WmcidRL3ABq7qhWHUsrG

charneykaye and others added 2 commits August 22, 2026 05:06
…irst conversation

The first conversation decides whether there is a second one. The
text-only demo (fake runtime: the same hard-coded reply every turn) and
the scripted tutorial taught a new player 'this is a bad chatbot' at the
exact moment of maximum skepticism. Both are gone from every user-facing
surface; the fake/scripted runtimes remain as internal test/dev infra.

Fixes #473

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C9WmcidRL3ABq7qhWHUsrG
…uites

The issue-#473 backstop refuses unpinned sessions that would resolve to
the fake/scripted runtimes; these suites run outside services/convsim-core
and were missed in the first pass. Swap-runtime tests stay unpinned and
activate a real selection instead, so they keep following app.state.runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C9WmcidRL3ABq7qhWHUsrG
@charneykaye
charneykaye merged commit 217c9b9 into main Aug 22, 2026
21 checks passed
@charneykaye
charneykaye deleted the feat/single-road-first-run branch August 22, 2026 12:29
charneykaye added a commit that referenced this pull request Aug 22, 2026
Follow-up 360 cleanup pass over #474.

Three containers in the first-run welcome and installing steps carried
an `aria-label` equal to their own visible heading:
- Welcome "Not a chatbot. Not a mirror." promise note
- Installing "While that downloads…" section
- Installing "Your first missions" list (labelled by its visible `<h3>`)

Each caused a screen reader to announce the heading twice ([duplicating
visible text in aria-label is a documented
anti-pattern](https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/)).
Removed the redundant labels; the visible headings remain the accessible
names, and content is announced once.

The one genuinely non-redundant label — the how-to-play ordered list,
whose "How to play" heading is not rendered visually — is intentionally
kept.

No visual change. tsc clean, eslint unchanged from baseline, `vite
build` clean, and FirstRunWizard's 72 tests (including the
while-you-wait content assertions) pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01C9WmcidRL3ABq7qhWHUsrG

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant