Ungraded Minds — product roadmap

Now building 3 · Needs attention 2 · Backlog 19 · Shipped 37 (of 39 review:done; 2 needing fixes shown above) . Last generated 2026-10-12 17:44 UTC, from git f9c4637+local changes. Source: .ai/sdd gates (specs' .status, PLAN.md, INDEX.md). Live app: https://app.ungradedminds.com

Now building

Hosting on Railway behind Cloudflareimplementation:in-progress014-hosting-railway-cloudflare
Status: Approved (owner, 2026-10-05)
Source: Owner's request, 2026-10-05 ("I want to deploy the app to a Cloudflare hosted domain"; then "want to host on railway.com"). Answers to Q-001–Q-010 on 2026-10-05. Extends 001-ai-projects-core NFR-001 and FR-036, and the 001 constraint "Runs locally only"
Last Updated: 2026-10-05

Overview

Today the app runs only on the owner's Mac, at localhost, with no sign-in.

This spec puts a second copy of the app online:

Business Context

Goals

Non-Goals / Out of Scope

User Stories

US-001: Use the app from anywhere

As the owner I want to open the app at my own domain from any browser So that I can use it when I'm away from my Mac or when it's off

Acceptance Criteria:

US-002: Only I can get in

As the owner I want a sign-in gate in front of the whole hosted app So that nobody else can read my details and chats or spend my paid keys

Acceptance Criteria:

US-003: Release a new version

As the owner I want to put my latest version online with one command on my Mac So that I decide exactly when the hosted app changes

Acceptance Criteria:

US-004: Keep using it locally

As the owner I want the local copy to work exactly as today So that I can keep developing and using it on my Mac

Acceptance Criteria:

Functional Requirements

Access

FR-001: The app at the owner's domain — Must Have

WHEN the owner opens the domain in a browser THE SYSTEM SHALL serve the hosted app over a secure (https) connection, after the sign-in (FR-002).

IF the domain is opened with plain http:// THE SYSTEM SHALL send the browser to the same page on https://.

The domain is bought and managed on Cloudflare by the owner (D-004). The hosted app runs on Railway (D-002).

FR-002: Sign-in before anything — Must Have

WHEN a browser that isn't signed in asks the hosted app for anything (a page, the app's data, a button press, research) THE SYSTEM SHALL show only the sign-in page, or refuse the request, SO THAT nothing of the app or its data is shown or changed before the sign-in.

*Extends 001 NFR-001 ("One local user, with no sign-in"): the local copy keeps no sign-in (FR-013); the hosted copy has one.*

FR-003: Sign-in with an email code, owner only — Superseded by 023 FR-001

Superseded by 023 FR-001 (2026-10-07): any address on the list in the hosting settings signs in this way; the list holds the owner and people acting for them (023-sign-in-email-list). The original text is kept below for history.

WHEN someone enters an email address on the sign-in page IF it is the owner's address THE SYSTEM SHALL email a one-time code to it, and open the app when the code is entered.

IF it is any other address, or the code is wrong or expired THE SYSTEM SHALL not let them in.

The owner's address is set in the hosting settings, not in the code (D-005).

FR-004: Staying signed in — Must Have

WHEN the owner has signed in on a browser THE SYSTEM SHALL keep that browser signed in for 7 days, then ask for a new code (D-006).

FR-005: No way around the sign-in — Must Have

THE SYSTEM SHALL not offer the hosted app, or any part of it, at any address that skips the sign-in, including the address the hosting service gives the app by default.

The hosted app

FR-006: Everything works online — Must Have

WHEN the owner uses the hosted app after signing in THE SYSTEM SHALL behave as the local app does under the current specs, including:

FR-007: Long research isn't cut off — Must Have

WHEN research runs on the hosted app THE SYSTEM SHALL show it live and let it run until it finishes or reaches the research time limit (10 minutes by default, 003 NFR-002), as on the Mac. The connection through the domain must not end it earlier.

FR-008: The hosted data is kept — Must Have

THE SYSTEM SHALL keep the hosted copy's data (details, projects, chats, research, options, sources, marks, reminders) across restarts of the hosted app and across releases.

*Extends 001 FR-036: the hosted copy keeps its own database on the hosting service; the local copy keeps backend/data/app.db.*

FR-009: The hosted copy starts empty — Must Have

WHEN the hosted app is opened for the first time THE SYSTEM SHALL start with no data and ask for the user details, as a new local install does (D-003).

FR-010: Hosted settings and keys — Must Have

THE SYSTEM SHALL take the hosted copy's settings (the AI model, provider keys, search key, TypeSafe key, Opik settings, the owner's email address) from the hosting service's settings. They are never stored in the code repository.

*The "owner's email address" item is superseded by 023 FR-002 (2026-10-07): a list of one or more allowed addresses. The rest of FR-010 stands.*

The same settings as the local settings file are available; local-only models (Ollama) are not usable online (Out of Scope). A missing or wrong key behaves as it does locally: the app starts, and the problem shows as an error when it is used (001 FR-035).

Releasing

FR-011: One release command — Must Have

WHEN the owner runs the release command on the Mac THE SYSTEM SHALL publish the app as it is on the Mac at that moment, and the domain shows the new version once the release finishes (D-007).

Pushing to GitLab, or any other action, shall not release.

FR-012: What a release never sends — Must Have

THE SYSTEM SHALL never send the local settings file (backend/.env, with its keys) or the local data folder (backend/data/, with the local database) to the hosting service in a release.

Local use

FR-013: Local use unchanged — Must Have

THE SYSTEM SHALL keep the local copy working exactly as today: the same start commands, localhost, no sign-in, its own database (D-009).

Documentation

FR-014: Hosting guide — Must Have

THE SYSTEM SHALL include a short hosting section in the README that covers:

Non-Functional Requirements

NFR-001: Security / Privacy

NFR-002: Reliability

NFR-003: Performance

NFR-004: Usability

NFR-005: Cost

User Experience Notes

Constraints

The real checks (P-005) need all of these. Until the owner has them, only the local parts can be checked.

Decisions

D-001: Only the owner, behind a sign-in gate

Decision: The hosted app has one user, the owner. A sign-in gate stands in front of all of it. Data stays shared as today (one set of details, projects and chats). *Changed by 023 D-001 and D-002 (2026-10-07): the owner and people acting for them, all sharing the one copy of the data.* Reason: Without a gate, anyone could read the owner's details and chats and spend the paid keys. Real multi-user support would change almost every spec. Source: Q-001 (owner, 2026-10-05) Impacts: FR-002 to FR-005, US-002, Out of Scope

D-002: Hosted on Railway, reached through a Cloudflare domain

Decision: The app runs on Railway. The domain is managed on Cloudflare and points to it. Reason: Owner's choice; works when the Mac is off. Source: Q-002 (owner, 2026-10-05) and the original request Impacts: FR-001, FR-008, FR-010, NFR-001, NFR-005

D-003: The hosted copy starts fresh

Decision: No local data is copied to the hosted app. Source: Q-003 (owner, 2026-10-05) Impacts: FR-009, Out of Scope

D-004: The domain is still to be bought

Decision: The owner buys a domain on Cloudflare. This is a prerequisite outside the app. Source: Q-004 (owner, 2026-10-05) Impacts: FR-001, Constraints

D-005: Sign-in with an email one-time code

Decision: The owner signs in by entering their email address and the code sent to it. Only the owner's address is allowed. *Changed by 023 D-002 (2026-10-07): the addresses on the list are allowed (023 FR-001).* Reason: No password to manage or leak. Source: Q-005 (owner, 2026-10-05) Impacts: FR-003

D-006: A sign-in lasts 7 days

Source: Q-006 (owner, 2026-10-05) Impacts: FR-004, NFR-004

D-007: Releases are one command, run by the owner

Decision: A new version goes live only when the owner runs the release command on the Mac. Reason: Nothing goes live by accident, and it works with the code on GitLab. Source: Q-007 (owner, 2026-10-05) Impacts: FR-011, Out of Scope

D-008: No backups

Decision: The hosted data has no backups. Source: Q-008 (owner, 2026-10-05) Impacts: Out of Scope, FR-014, Risks

D-009: Local and hosted side by side

Decision: The local copy keeps working as today, with its own data, separate from the hosted copy. Source: Q-009 (owner, 2026-10-05) Impacts: FR-013, US-004

D-010: Sign-out through an address in the README

Decision: The app's pages don't change. The README gives the address that ends the sign-in on the current browser. Reason: The owner mostly uses their own devices; the sign-in service already offers sign-out. Source: Q-010 (owner, 2026-10-05) Impacts: FR-014

Questions

Q-001: Who can use the hosted app?

Status: answered Answer: Only the owner, behind a sign-in gate. Decision: D-001

Q-002: Must it work when the Mac is off?

Status: answered Answer: Yes: host on Railway. Decision: D-002

Q-003: What happens to the existing data?

Status: answered Answer: Start fresh. Decision: D-003

Q-004: Which address?

Status: answered Answer: No domain yet; one will be bought. Decision: D-004

Q-005: How does the owner sign in?

Status: answered Answer: Email one-time code. Decision: D-005

Q-006: How long does a sign-in last?

Status: answered Answer: 7 days. Decision: D-006

Q-007: How does a new version go live?

Status: answered Answer: One deploy command from the Mac. Decision: D-007

Q-008: Backups of the hosted data?

Status: answered Answer: No backups. Decision: D-008

Q-009: Does local use keep working?

Status: answered Answer: Yes, both. Decision: D-009

Q-010: How does the owner sign out?

Status: answered Answer: A sign-out address, written in the README. Decision: D-010

Superseded Baseline (to Mark at Review, P-001)

These are extended, not replaced: they stay true for the local copy.

Success Metrics

MetricTarget / SignalNotes
Done-whenWith the Mac off, from a browser that never visited: https://<domain> → sign-in → code by email → details form → a guided run reaches four options with sources and trust labels; a mark, a reminder with a notification, a round and Research again with Confirm all workNeeds the owner's domain, Railway and Cloudflare accounts, and keys
GateA browser without sign-in, another email address, and the hosting service's own address for the app all fail to show anything of the app or its data
ReleasesAfter a release, the hosted data is unchanged; the release sent neither backend/.env nor backend/data/
Locallocalhost works as before, with its own data

Risks and Mitigations

RiskImpactMitigation
Hosted data is lost (account, plan or storage problem) with no backupMediumOwner's choice (D-008); stated in the README (FR-014). Backups can be a later spec
The hosting service's own address bypasses the gateHighFR-005; checked at review
Long research is cut off by the connection between the domain and the hosted appHighFR-007; checked with a real research run of several minutes
A release publishes unfinished local changes, because it sends the app as it is on the MacMediumThe owner runs releases on purpose (D-007); the README says what is sent
Times on the hosted server differ from the owner's time zoneLowReminder times are already chosen in the browser (009); checked with a reminder at review
Paid keys used by an unwanted visitorHighFR-002 to FR-005
Monthly cost higher than expectedLowOne service, one data store (NFR-005); costs stated in the README

Glossary

The seven-step journeyimplementation:in-progress018-journey-stepper
Status: Approved (2026-10-06; amended at design approval the same day: FR-006, Q-005; amended the same day after moving onto main: renumbered from 017, spec 017's look, Superseded Baseline for 017 — re-confirmed by the owner with the tasks, 2026-10-06)
Source: Owner's PRD "The seven-step journey (stepper)", based on the owner's Questions-step mockup, 2026-10-06; approved by the owner the same day with D-001–D-010 and the proposed answers to Q-001, Q-002, Q-004 and Q-005. Part of the stepper redesign. Changes 011-single-page-chat-collapsible-sidebar (one page, section index, where a chat opens), through it 008-step-navigation-research-again, and the section-index lines of 017-new-look-ungraded-minds. Drafted as 017 and renumbered to 018 on 2026-10-06, because main had shipped 017 (the new look) in the meantime (P-004)
Last Updated: 2026-10-06

Overview

Today a chat is one long page with sections in time order (Questions, Research, Options, Round N, Research N) and a small index of marks next to the scrollbar (spec 011).

This spec turns a chat into a guided journey of seven steps in three groups:

DiscoverDecideAct
Questions · Research · OptionsEvaluate · Compare · ChooseNext steps

This spec:

The redesign has other parts. The look (colours, type, line icons, the name Ungraded Minds) has shipped as spec 017, and the stepper is built in that look. The app shell, the goal bar, the Questions page redesign, and the Evaluate, Compare, Choose and Next steps pages each get their own spec.

Business Context

Goals

Non-Goals / Out of Scope

User Stories

US-001: See where I am

As the student I want to see all seven steps, which ones are done and which one I'm on So that I know how far I've come and what's next

Acceptance Criteria:

US-002: Go back and forth freely

As the student I want to open any step I've reached So that I can re-read my answers or the research without losing my place

Acceptance Criteria:

US-003: Be moved along when something finishes

As the student I want the app to take me to the next step when the AI finishes So that I don't have to hunt for the result

Acceptance Criteria:

US-004: Nothing I could do before is lost

As the student I want every current feature to still be there So that the new layout doesn't cost me anything

Acceptance Criteria:

Functional Requirements

Stepper

FR-001: The stepper bar — Partly superseded by 026 FR-010, 028 FR-001 and 034 FR-001, FR-002

Partly superseded by 026 FR-010 (2026-10-07) (026-question-tone-and-limits): the first step is named Reflections on screen; the rest of the bar is unchanged.

Partly superseded by 028 FR-001 (2026-10-08) (028-your-story-paths): the first step is named Your story.

Partly superseded by 034 FR-001 and FR-002 (2026-10-09) (034-summit-and-compass): the bar is drawn as a winding trail, with a Compass tab at the left end and a Summit tab at the right end (tabs, not steps), and a boot where the journey is.

WHILE a journey (chat) is open THE SYSTEM SHALL show a stepper bar above the step page with three groups, in this order, each with a small uppercase label:

Each step shows a state mark (FR-002) and its name.

FR-002: Step states — Must Have — Partly superseded by 034 FR-002, FR-003

Partly superseded by 034 FR-002 and FR-003 (2026-10-09) (034-summit-and-compass): the Compass and Summit tabs have no state mark; while Scout or Compass is in progress or at its checkpoint, the journey is on that tab, so no step is in progress.

THE SYSTEM SHALL show each step in exactly one state:

StateMeaningLook
DoneThe journey has moved past ita tick
In progressWhere the journey is nowa filled circle
AvailableUnlocked, but neither done nor in progressan empty circle
LockedNot reachable yetmuted, with a lock, can't be clicked

At most one step is In progress (FR-003).

Separately, the step being viewed is highlighted with a soft coloured background, and screen readers hear that it is the current step (NFR-002). The viewed step and the in-progress step are often the same, but not always.

FR-003: Unlock and progress rules — Must Have — Partly superseded by 034 FR-003

Partly superseded by 034 FR-003 (2026-10-09) (034-summit-and-compass): while Scout or Compass is in progress or waits at its checkpoint, its tab is where the journey is (rule 2 then names that tab, not Questions).

THE SYSTEM SHALL work out each step's state from what is already saved for the journey (and, for a failed Research again, from the page as it is now), never from a separately saved status (D-003).

The in-progress step is the first of these that applies:

  1. Research, while a research run is running, a Research again run waits for confirmation, or the latest research didn't finish (its notice with Retry is showing);
  2. Questions, while the AI is asking, the journey waits for an answer (the first questions or a round), or a question didn't arrive (its notice with Retry is showing);
  3. Options, once the journey has options;
  4. otherwise Questions.

Chats from before saved options and read-only chats follow FR-016 instead.

Unlock and done rules:

StepUnlocked whenDone when
Questionsalwaysresearch has started at least once, and Questions isn't in progress
Researchthe first research run has startedthe journey has options, and Research isn't in progress
Optionsthe journey has optionsnever in this spec (the Evaluate spec decides)
Evaluateits spec has shipped and the journey has optionsas its spec decides
Compareits spec has shipped and 2 or more options are shortlistedas its spec decides
Chooseits spec has shipped and 1 or more options are shortlistedas its spec decides
Next stepsits spec has shipped and an option is chosenas its spec decides

An unlocked step that is neither done nor in progress is Available.

Until their specs ship, Evaluate, Compare, Choose and Next steps are Locked with the reason "Coming soon".

A step that was unlocked locks again only if the saved data it depends on goes away (for example, later: clearing every shortlist mark locks Compare and Choose again). If that step is being viewed, its page stays and says why it is now locked, instead of vanishing.

FR-004: Locked-step reasons — Must Have

WHEN the student hovers over or focuses a locked step THE SYSTEM SHALL show why it's locked, for example:

FR-005: Moving between steps — Must Have

WHEN the student clicks an unlocked step, or chooses it with the keyboard THE SYSTEM SHALL show that step's page at once. This sends nothing to the server, uses no AI and adds nothing to the chat. It also works while the AI is working (as 011 D-009).

The first time a step is shown after the journey is opened, its page starts at the top, except Questions during a conversation, which starts at the latest question. When the student returns to a step within the same open journey, it shows as they left it: the same place on the page, the same open or closed research lists, the same level tab and the same card in each options viewer (D-009).

FR-006: Remembering the step — Should Have

THE SYSTEM SHALL keep the open journey and its viewed step in the page address, so a reload reopens the same journey on the same step (D-006). It SHALL also remember the last viewed step of each journey in this browser, so reopening a journey from the list returns to that step.

Opening a journey and leaving it also add a Back entry, so the browser's Back button can return to the journey and step shown before (Q-005). *Added at design approval, 2026-10-06.*

FR-007 overrides both when something needs the student's attention.

FR-007: Where a journey opens — Must Have — Partly superseded by 034 FR-011

Partly superseded by 034 FR-011 (2026-10-09) (034-summit-and-compass): rule 2 opens the tab holding the waiting question, the missing question (Retry) or the waiting checkpoint.

WHEN a journey is opened (from the list, by a reload, or from a reminder) THE SYSTEM SHALL show the first step that applies:

  1. A Research again run waits for confirmation → Research, with its confirm list in view.
  2. The AI asked a question that isn't answered yet, or a question didn't arrive (Retry) → Questions.
  3. A turn is still running in the background → that turn's step (Questions or Research), with "Still working…".
  4. A reminder was opened (009 FR-006, FR-007) → Options, with that option's card brought into view and highlighted.
  5. The remembered step (FR-006), if it is still unlocked.
  6. Otherwise, the journey's in-progress step (FR-003), or the step FR-016 names for older chats.

*Replaces 011 FR-007.*

FR-008: Automatic moves — Must Have — Partly superseded by 034 FR-011

Partly superseded by 034 FR-011 (2026-10-09) (034-summit-and-compass): choosing or changing to Scout or Compass shows its tab; the checkpoint's other-path button shows its tab; Start looking shows Research.

WHEN the student presses a button that starts or settles work THE SYSTEM SHALL show the step where its result appears:

WHILE the student is viewing the step where the AI is working THE SYSTEM SHALL move them along when:

IF the student is viewing a different step when one of these happens THE SYSTEM SHALL not move them. Instead it shows an "updated" dot on the step that changed, and removes the dot when the student views that step (D-005). The dots last while the journey stays open.

How today's flow maps onto the steps

FR-009: Questions step — Partly superseded by 026 FR-010 and 028 FR-001, FR-009, FR-012

Partly superseded by 026 FR-010 (2026-10-07): the page and its title are Reflections; the rest is unchanged.

Partly superseded by 028 FR-001, FR-009 and FR-012 (2026-10-08): the page is Your story; in journeys started since 028 it holds the path chooser, the progress pill ("Question N of about M · You're on: … · change") and the checkpoint cards (028-your-story-paths).

THE SYSTEM SHALL show on the Questions page:

*Replaces 011 FR-004 (Go to options brought the Options section into view) and 011 FR-006 (the message box at the bottom of every chat).*

FR-010: Research step — Must Have

THE SYSTEM SHALL show on the Research page:

*Replaces 011 FR-005 (a new Research N section at the bottom of the page).*

FR-011: Options step — Must Have

THE SYSTEM SHALL show on the Options page everything in today's Options section, with the same behaviour:

WHILE a Research again run waits for confirmation THE SYSTEM SHALL keep the Options page read-only, as today (marks, Remind and Add more about me unavailable, Research again hidden), and show the note "Confirm or discard the new research first." with a link to the confirm list on Research (D-010).

WHILE research runs or the AI is writing THE SYSTEM SHALL keep the mark buttons, Remind, Research again and Add more about me unavailable, as today (008 FR-005).

*Replaces 011 FR-003 (the Options section after the first research).*

FR-012: Locked step pages — Must Have

THE SYSTEM SHALL never show a locked step's page because of a click. IF a remembered step or a page address points to a step that is now locked, THE SYSTEM SHALL show the journey's in-progress step instead (or the step FR-016 names for older chats).

FR-013: Step page header — Must Have

THE SYSTEM SHALL start every step page with its title and a one-line subtitle (see User Experience Notes). Later specs may add a short status on the right of the header (for example "Question 4 of about 8" or "4 of 6 marked"). This spec adds none.

FR-014: Continue button — Should Have

WHEN the step after the viewed one is unlocked THE SYSTEM SHALL show a Continue to <step> button at the bottom of the page, which shows that step. Example: on Research, once options exist, "Continue to Options". Pressing it sends nothing to the server.

Removed

FR-015: No one-page chat, no section index — Must Have

THE SYSTEM SHALL no longer show the one-page chat with its section headings, or the index of marks next to the scrollbar.

*Replaces 011 FR-001, FR-002 and FR-008 to FR-012.*

Older chats

FR-016: Chats from before guided recommendations and before saved options — Partly superseded by 020 FR-012

Partly superseded by 020 FR-012 (2026-10-06): the lock reasons and notices say "journey" instead of "chat" ("This journey is from before guided recommendations.", "This journey is from before saved options.", "This journey is finished."), and New chat is New journey (020-my-goals-onboarding). The original text is kept below for history.

THE SYSTEM SHALL show older chats in the stepper as follows (D-008):

A chat from before saved options whose research failed follows FR-003: Research is in progress with Retry, and a successful Retry saves options as in any other chat.

Non-Functional Requirements

NFR-001: Speed

NFR-002: Accessibility

NFR-003: Narrow windows

Kept, and made true by 036 FR-001, FR-004 and FR-005 (2026-10-09) (036-compact-stepper-sidebar-summary): the stepper had been scrolling sideways at every supported width. Since 036 it fits on one row from 1,280px to 1,920px, with only a small scroll at the narrowest windows with the sidebar open, and still scrolls below about 640px.

NFR-004: No lost behaviour

NFR-005: Reliability

User Experience Notes

Constraints

Decisions

D-001: One page per step

Decision: Each step has its own page. Rounds and research runs keep their time order inside their step. Reason: It matches the mockup and keeps each page short. It reverses 011 D-001 (one page in time order), but the history stays readable because time order is kept inside each step. Source: Owner's PRD; Q-001 (confirmed at approval, 2026-10-06) Impacts: FR-005, FR-009 to FR-011, FR-015

D-002: All seven steps are defined now, four of them locked

Decision: The stepper always shows all seven steps. Evaluate, Compare, Choose and Next steps are Locked with "Coming soon" until their specs ship. Reason: The student sees the whole path from day one, and later specs only fill in pages and unlock rules. Source: Owner's PRD; Q-002 (confirmed at approval, 2026-10-06) Impacts: FR-001, FR-003, FR-004

D-003: Step states are worked out, not saved

Decision: Each step's state comes from the journey's existing data every time it is shown. Reason: No new data, no upgrade of the database, and states can't drift from the real data. Source: Owner's PRD (confirmed at approval, 2026-10-06) Impacts: FR-002, FR-003, Constraints

D-004: Rounds belong to Questions, runs belong to Research

Decision: "Round N" becomes a sub-heading on Questions, and each research run is "Research N" on Research. They are no longer top-level parts of the page. Reason: Each step then holds one kind of activity. Source: Owner's PRD (confirmed at approval, 2026-10-06) Impacts: FR-009, FR-010

D-005: Automatic moves only when the student is following the work

Decision: The app moves the student only if they are viewing the step where the AI is working, or they pressed the button that started or settled the work. Otherwise the changed step gets a dot. Reason: It keeps 011's rule of never pulling the reader away (011 D-009). Source: Owner's PRD (confirmed at approval, 2026-10-06) Impacts: FR-008, NFR-005

D-006: The page address holds the journey and the step

Decision: The page address names the open journey and its viewed step, so a reload reopens both. The last viewed step of each journey is also remembered in this browser. Reason: US-002 asks that a reload keeps the step. Today a reload doesn't even keep the open chat, so the address must name the journey too. An address also works with the browser's Back button (Q-005). Source: Owner's PRD recommends the address; Q-004. Naming the journey in it was proposed in the draft and confirmed at approval (2026-10-06) Impacts: FR-006, FR-007, FR-012

D-007: The message box only on Questions

Decision: The message box is at the bottom of the Questions page and nowhere else. Add more about me moves the student there. Reason: Typing is answering questions, which is the Questions step. Today's message box is at the bottom of every chat (011 FR-006); keeping it on every step would put a second way of adding information on Research and Options. Source: Proposed in the draft, confirmed by the owner at approval (2026-10-06) Impacts: FR-009, FR-011

D-008: Older chats get fixed step states

Decision: Read-only chats from before guided recommendations show only Questions. Finished chats from before saved options show Questions and Research as Done, open on Research and keep Options locked. Reason: These chats can't reach options, so the general rules (FR-003) would leave them with no sensible step. The owner's database has both kinds (chats 2 and 5). Source: Proposed in the draft, confirmed by the owner at approval (2026-10-06) Impacts: FR-003, FR-007, FR-016

D-009: Returning to a step keeps it as it was

Decision: The first time a step is shown after opening a journey, it starts at the top (Questions in a conversation: at the latest question). Returning to it within the same open journey shows it as the student left it. Reason: The owner's PRD asked for both "starts at the top" (FR-005) and "shows it as I left it" (US-002). This reading satisfies both. Source: Proposed in the draft, confirmed by the owner at approval (2026-10-06) Impacts: FR-005

D-010: A note on Options while a confirm list waits

Decision: While a Research again run waits for confirmation, the Options page shows "Confirm or discard the new research first." with a link to the confirm list. Reason: Today this note sits above the message box, and the Options section is read-only without saying why. With one page per step, the confirm list is on another page, so Options needs to say where to go. Source: Owner's PRD (it described this as today's behaviour; today the note is only above the message box, with no link). Confirmed at approval (2026-10-06) Impacts: FR-011

Questions

Q-001: One page per step, or one scrolling page with the stepper as its index?

Status: answered (owner, at approval, 2026-10-06) Answer: One page per step (D-001).

Q-002: Show the four locked steps now, or hide them until they're built?

Status: answered (owner, at approval, 2026-10-06) Answer: Show them, locked with "Coming soon", so the student sees the full path (D-002).

Q-003: Where should a reminder open once Evaluate and Next steps exist?

Status: deferred to the Evaluate and Next steps specs Answer for now: Options (FR-007). Probably Next steps later.

Q-004: Keep the step in the page address, or in browser storage only?

Status: answered (owner, at approval, 2026-10-06) Answer: In the address, together with the journey, plus the last step per journey in browser storage for reopening from the list (D-006).

Q-005: Should the browser's Back button move between steps?

Status: answered (owner, at approval, 2026-10-06) Answer: Yes for steps the student chose (a click, Continue, Go to options, Add more about me). Automatic moves (FR-008) don't add a Back entry, so Back never lands on a page the student didn't choose. Amended at design approval (2026-10-06): opening and leaving a journey also add a Back entry (FR-006).

Superseded Baseline (to Mark at Review, P-001)

Success Metrics

MetricTarget / SignalNotes
Done-whenA new journey: Questions → automatic move to Research (live) → automatic move to Options. Jumping back to Questions and Research and forward again sends no requests (browser network tab). A reload keeps the journey and step. Decide and Act steps are locked with their reasonsChecked in the browser with a real model
No lost behaviourMark, rule out with a reason, Remind, level tabs, viewer swipes and keys, Research again → Confirm → Options, Add more about me → round → Research again, Retry after a forced failure, reopening during a background turnChecked in the browser
Existing chatsEvery chat in a copy of the owner's database opens on the right step without errorsIncluding the legacy chat 2 and the pre-005 chat 5
ComprehensionThe owner, or a test student, can name the current step and what unlocks the next oneAsked without help

Risks and Mitigations

RiskImpactMitigation
Reverses spec 011 shortly after it shippedMediumRounds and runs keep their time order inside steps; settle Q-001 before design
The student misses a result that finished on another stepMediumThe "updated" dot (FR-008) and Continue buttons (FR-014)
Four locked steps feel like a broken promiseLowClear "Coming soon" reasons; the Evaluate spec comes next
Rebuilding the Options page makes 012 Issue 1 worseMediumFix 012 Issue 1 first (Constraints)
A background turn's step can't be told from what the page loads (round or Research again)MediumThe design checks this first. FR-007 point 3 needs it, and the server must not change

Glossary

Open Questions

DeepSeek first, Gemini fallbackimplementation:in-progress019-deepseek-default-gemini-fallback
Status: Approved (2026-10-06)
Source: Owner's requests, 2026-10-06: "I want to change the default model for thinking / discovery to deepseek. If tokens finish use fallback as gemini" (Q-001 to Q-005), then "I also want a settings tab on the left which can be used to toggle the thinking and research models independently" (Q-006 to Q-009). Changes 013-deepseek-firecrawl FR-001, FR-003 and D-005, 001-ai-projects-core FR-025 and FR-034, 003-guided-recommendations FR-016 and FR-018, and 016-reset-all-data FR-003 (see Superseded Baseline)
Last Updated: 2026-10-06 (approved by the owner as drafted, including D-007, D-008 and D-011; renumbered from 018 to 019 because 018 is used in another worktree)

Overview

Today the owner's copies of the app (local and hosted) use Google Gemini for everything: the questions ("Thinking…") and the research. The model can only be changed in the backend settings file, followed by a restart.

With this spec:

Business Context

Goals

Non-Goals / Out of Scope

User Stories

US-001: DeepSeek runs the app

As the owner I want DeepSeek to ask the questions and do the research by default So that the app runs on the cheaper model

Acceptance Criteria:

US-002: Gemini takes over when DeepSeek's credit runs out

As the owner I want Gemini to finish the work when DeepSeek is out of credit So that chats keep working until I top up

Acceptance Criteria:

US-003: Choose the models on a Settings page

As the owner I want a Settings page in the sidebar where I choose the Thinking model and the Research model separately So that I can switch models without editing files or restarting

Acceptance Criteria:

Functional Requirements

Models

FR-001: DeepSeek is the starting model — Must Have

THE SYSTEM SHALL start with DeepSeek (deepseek:deepseek-flash, D-007) as the Thinking model and the Research model in the owner's local and hosted copies and in the settings template, until another model is chosen on the Settings page (FR-010).

Gemini (the model used today) is the fallback model in the same places (FR-002).

FR-002: A fallback model setting — Must Have

THE SYSTEM SHALL offer a backend setting for a fallback model, in the same "provider:model" form as the other model settings. One fallback model serves both stages. Changing it requires restarting the backend.

IF no fallback model is set THE SYSTEM SHALL behave exactly as today: DeepSeek running out of credit shows a Model error or Research error with Retry (013 FR-003).

IF the fallback model is set but its key is missing or wrong THE SYSTEM SHALL still start, and the problem shows only if the fallback is needed (FR-006).

FR-003: Switching when DeepSeek is out of credit — Must Have

WHEN a DeepSeek model refuses a request because the DeepSeek account is out of credit IF a fallback model is set THE SYSTEM SHALL do that step with the fallback model and finish the turn, without showing a Model error or Research error and without asking for Retry.

This applies to every step that uses the AI:

The student's answers, the searches already shown and everything saved earlier stay as they are. Once a turn has switched, the rest of that turn uses the fallback model (D-008).

FR-004: Only DeepSeek running out of credit switches — Partly superseded by 030 FR-005 and FR-006

Partly superseded by 030 FR-005 and FR-006 (2026-10-08) (030-opencode-go-models): an OpenCode Go model that refuses because Go's usage limit is reached switches to the Go fallback (OPENCODE_GO_FALLBACK_MODEL, DeepSeek Flash). Every other failure of a non-DeepSeek model still shows the usual error. The original text is kept below for history.

IF a DeepSeek model fails for any other reason (missing or wrong key, rate limit, overload, outage, refused request, unknown model) OR the stage is set to a model that isn't DeepSeek, and that model fails THE SYSTEM SHALL NOT use the fallback model. It shows the Model error or Research error with Retry, exactly as today (001 FR-025, 003 FR-016, 013 FR-003).

FR-005: The chosen model again on every new turn — Must Have

WHEN a new turn starts (a new chat's first question, an answer, a round, Research again, or Retry) THE SYSTEM SHALL try the model chosen for that stage first, even if an earlier turn switched to the fallback.

This means the app goes back to DeepSeek on its own after a top-up, without a restart.

FR-006: When the fallback fails too — Must Have

IF DeepSeek is out of credit and the fallback model then fails THE SYSTEM SHALL show the usual Model error (questions) or Research error (research) with Retry, and the message says both: "DeepSeek is out of credit, and the fallback model failed: <details>".

The note

FR-007: Telling the owner about a switch — Partly superseded by 030 FR-008

Partly superseded by 030 FR-008 (2026-10-08): a switch from an OpenCode Go model shows its own note, "OpenCode Go has reached its usage limit, so DeepSeek Flash answered. Go's limit resets on its own, or pick another model in Settings.", in the same place and style. The original text is kept below for history.

WHEN a turn switched to the fallback model THE SYSTEM SHALL:

The note shows once per turn that switched, not once per step. It is not saved with the chat.

The Settings page

FR-008: Opening Settings — Partly superseded by 021 FR-001 and 033 FR-005

Partly superseded by 021 FR-001 (2026-10-07) (021-sidebar-menu): Settings is the last menu entry, pinned at the bottom of the sidebar below Reminders (no longer "Reminders due"); on the collapsed strip it is the last of the four menu icons. The original text is kept below for history.

Partly superseded by 033 FR-005 (2026-10-12) (033-deep-research-toggle): while Deep Research is on, that page's Research model dropdown is disabled; its current value is still shown.

THE SYSTEM SHALL show a Settings entry in the sidebar, below Reminders due. It is also reachable when the sidebar is collapsed (011), as an icon with the name "Settings" on hover. It opens the Settings page in the main area, as Reminders due does (009). In the hosted copy, it is behind the sign-in like every other page (014).

FR-009: The list of models — Partly superseded by 030 FR-001

Partly superseded by 030 FR-001 (2026-10-08): the owner's copies and the template also list Kimi K2.6, DeepSeek V4 Flash and GLM-5.3 Flash from OpenCode Go (opencode-go:<model>), each marked "(OpenCode Go)". The original text is kept below for history.

THE SYSTEM SHALL offer, for both choices, the models listed in a backend setting, each shown by a readable name (for example "DeepSeek Flash", "DeepSeek V4 Pro", "Gemini 3.8 Flash"). The starting models (FR-001) are always in the list, even if the setting leaves them out. Changing the list requires restarting the backend.

The owner's copies and the template list DeepSeek Flash, DeepSeek V4 Pro and Gemini 3.8 Flash (D-009).

FR-010: Choosing the Thinking and Research models — Partly superseded by 026 FR-010

Partly superseded by 026 FR-010 (2026-10-07) (026-question-tone-and-limits): the label reads Thinking (the reflections), because the journey's first step is called Reflections on screen. The two choices and how they save are unchanged.

THE SYSTEM SHALL show two choices on the Settings page, Thinking (the questions) and Research (research and option cards), each set to the model in use now.

WHEN the owner picks a different model for one of them THE SYSTEM SHALL save it at once, show that it was saved, and use it from the next turn of every chat, without a restart. The other choice doesn't change.

WHILE a turn is running THE SYSTEM SHALL let that turn finish on the models it started with.

FR-011: Keeping the choice — Partly superseded by 031 FR-007 and 033 FR-005

Partly superseded by 031 FR-007 (2026-10-08) (031-exa-web-search): a Reset also puts the Web Search choice back to the starting service, and that choice is kept the same way. The original text is kept below for history.

Partly superseded by 033 FR-005 (2026-10-12) (033-deep-research-toggle): while Deep Research is on, the Research model choice cannot be changed on the Settings page; it becomes changeable again when Deep Research is switched off.

THE SYSTEM SHALL keep the chosen models until they are changed on the Settings page, through backend restarts and releases.

WHEN a Reset is confirmed (016) THE SYSTEM SHALL put both choices back to the starting models (FR-001) (D-011). *Extended by 026 FR-004 (2026-10-07): the Reset also puts the question tone and limits back to Balanced, 1 and 5.*

IF a chosen model is no longer in the list (FR-009) THE SYSTEM SHALL use the starting model for that stage, and the page shows it as the choice.

FR-012: Showing the fallback — Partly superseded by 030 FR-009

Partly superseded by 030 FR-009 (2026-10-08): when the list has an OpenCode Go model, the same paragraph also shows "When OpenCode Go's limit is reached: DeepSeek Flash" (or "No fallback is set for OpenCode Go."). The original text is kept below for history.

THE SYSTEM SHALL show, below the two choices, which model takes over when DeepSeek is out of credit ("When DeepSeek is out of credit: Gemini 3.8 Flash"), or "No fallback is set." It can't be changed on the page (D-012).

Privacy

FR-013: What the models receive — Partly superseded by 030 FR-010

Partly superseded by 030 FR-010 (2026-10-08): the README and the template also name OpenCode Go and the provider behind each Go model, and OpenCode Go receives a random code per journey. Payloads are unchanged. The original text is kept below for history.

THE SYSTEM SHALL send the chosen model and the fallback model exactly what it sends any model today: the student's details without the name, the project and the answers, and the options with their marks and reasons (003 NFR-001, 013 FR-007). The README and the settings template must say that a chat's turns may go to more than one provider.

Non-Functional Requirements

NFR-001: Reliability

NFR-002: Time and cost

NFR-003: Usability and accessibility

NFR-004: Configuration

User Experience Notes

Constraints

Decisions

D-001: DeepSeek for the questions and for research

Decision: DeepSeek is the starting model for both the questions and research, including turning the recommendation into option cards. The Gemini fallback covers both. Reason: Owner's choice. It saves the most, and the fallback covers the risk 013 noted about DeepSeek's research. Source: Q-001 (owner, 2026-10-06) Impacts: FR-001, FR-003, US-001

D-002: Only running out of credit switches

Decision: Only DeepSeek's out-of-credit refusal switches to the fallback. Every other DeepSeek problem shows today's errors. Reason: "If tokens finish" means credit. A broken DeepSeek setup should be seen, not hidden behind Gemini (and Gemini's bill). Source: Q-002 (owner, 2026-10-06) Impacts: FR-003, FR-004, Out of Scope

D-003: A note in the app

Decision: A turn that switched shows an amber note in the chat and writes a log warning. Reason: The owner should know when to top up and that Gemini is being billed. Source: Q-003 (owner, 2026-10-06) Impacts: FR-007, US-002

D-004: The chosen model again on every new turn

Decision: Each new turn tries the chosen model first. Reason: After a top-up the app returns to DeepSeek by itself. The cost is one fast refused call per turn while the credit is empty. Source: Q-004 (owner, 2026-10-06) Impacts: FR-005, NFR-002

D-005: The owner's copies and the template, not the built-in default

Decision: The owner's local and hosted settings and the settings template start on DeepSeek with the Gemini fallback. Without any model setting, the app keeps its current built-in model and has no fallback. Reason: Owner's choice. Other setups keep working as before. Source: Q-005 (owner, 2026-10-06) Impacts: FR-001, FR-002, Out of Scope

D-006: "Thinking" means the questions stage

Decision: "Thinking" in the requests means the questions stage, which the chat shows as "Thinking…". It is not DeepSeek's thinking mode, which stays off (013). Reason: It matches the app's own label for that stage. Source: Drafting, 2026-10-06 Impacts: FR-010, Out of Scope

D-007: The DeepSeek model

Decision: The starting model is deepseek:deepseek-flash, the example from 013. DeepSeek V4 Pro is on the Settings page's list. Reason: It's the fast, cheaper model, like Gemini Flash today. Source: Drafting, 2026-10-06; confirmed by the owner at approval, 2026-10-06 Impacts: FR-001, FR-009

D-008: Once switched, the rest of the turn stays on the fallback

Decision: After a step switches, the remaining steps of that turn go straight to the fallback model, and the next turn tries the chosen model again. Reason: A zero balance won't recover within a few seconds. This avoids a refused call per step and repeated waits inside one research run. Source: Drafting, 2026-10-06; confirmed by the owner at approval, 2026-10-06 Impacts: FR-003, NFR-002

D-009: A fixed list of models

Decision: Each choice on the Settings page picks from a list of models set in the settings file, shown by readable names. The owner's copies list DeepSeek Flash, DeepSeek V4 Pro and Gemini 3.8 Flash. Reason: Owner's choice. More flexible than a two-way switch, and no typos, unlike a typed name. Source: Q-006 (owner, 2026-10-06) Impacts: FR-009, Out of Scope

D-010: No fallback for Gemini — Changed by 030 D-003

Changed by 030 D-003 (2026-10-08): OpenCode Go models have their own fallback for Go's usage limit. Gemini and other models still have none.

Decision: Only a DeepSeek model running out of credit switches to the fallback. A stage set to Gemini (or any other model) shows today's errors when it fails. Reason: Owner's choice. Gemini's limits are rate quotas, not prepaid credit, so "out" is hard to tell from "busy". Source: Q-007 (owner, 2026-10-06) Impacts: FR-004, Out of Scope

D-011: Choices are kept until changed; Reset puts them back

Decision: The chosen models are saved with the app's data and survive restarts and releases. The settings file gives only the starting choice. A Reset puts both back to the starting models. Reason: Owner's choice. The hosted copy shouldn't forget the choice on every release. Source: Q-008 (owner, 2026-10-06). The Reset part changes 016 FR-003, which keeps the settings through a Reset; confirmed by the owner at approval, 2026-10-06 Impacts: FR-011, Superseded Baseline

D-012: The fallback stays in the settings file — Changed by 026 D-005

Changed by 026 D-005 (2026-10-07): the page also has the Reflections section (tone, fewest and most questions). The fallback still stays in the settings file.

Decision: The Settings page has only the two model choices. The fallback model is set in the settings file and only shown on the page. Reason: Owner's choice. Smallest page. Source: Q-009 (owner, 2026-10-06) Impacts: FR-002, FR-012, Out of Scope

Questions

Q-001: Which stages use DeepSeek first?

Status: answered Answer: The questions and research. Decision: D-001

Q-002: What makes the app switch to Gemini?

Status: answered Answer: Only DeepSeek running out of credit. Decision: D-002

Q-003: Does the app tell the owner about a switch?

Status: answered Answer: Yes, with a small note in the app. Decision: D-003

Q-004: When does the app try DeepSeek again?

Status: answered Answer: On every new turn. Decision: D-004

Q-005: Where does the new default apply?

Status: answered Answer: The owner's local and hosted copies and the settings template. The built-in default doesn't change. Decision: D-005

Q-006: What can each Settings choice pick?

Status: answered Answer: Models from a fixed list. Decision: D-009

Q-007: Is there a fallback when a stage is set to Gemini?

Status: answered Answer: No. Decision: D-010

Q-008: How long does a choice last?

Status: answered Answer: Until changed; restarts and releases keep it. Decision: D-011

Q-009: Is the fallback switchable on the Settings page?

Status: answered Answer: No, it stays in the settings file. Decision: D-012

Superseded Baseline (to Mark at Review, P-001)

Success Metrics

MetricTarget / SignalNotes
Done-when (in credit)A new chat: questions → research → options → a round → Research again → Confirm, all on DeepSeek, with no noteNeeds DeepSeek credit
Done-when (out of credit)The same run completes on Gemini, with the note on each turn and no error cardNeeds an empty DeepSeek account or a simulated out-of-credit answer (Constraints)
RecoveryAfter DeepSeek works again, the next turn uses DeepSeek with no restart
SettingsResearch set to Gemini on the page → the next chat asks with DeepSeek and researches with Gemini, no restart; the choice survives a restart; a Reset puts it back to DeepSeek
No hidden failuresA wrong DeepSeek key → Model error with Retry, Gemini not used. No fallback set → today's error. A stage on Gemini failing → today's error

Risks and Mitigations

RiskImpactMitigation
DeepSeek handles research or the option cards poorly (013 risk)MediumChecked with a real run before review. Errors show with Retry. Research can be set to Gemini on the Settings page
The owner's DeepSeek account can't easily be emptied, so the real out-of-credit answer is never seen before releaseMediumDesign defines how the out-of-credit answer is recognised and how it's simulated for the check
Gemini quietly takes over for a long time and costs more than expectedLowThe note on every switched turn (FR-007) and the log warning
A turn that switches mid-research mixes both models' workLowAccepted (Constraints). The time limit still applies
A model on the list has no key set, and choosing it only fails on the next turnLowThe usual error with Retry; the owner picks another model on the page

Glossary

Needs attention — under review or needing fixes

A new look for Ungraded Mindsreview:done017-new-look-ungraded-minds
Status: Approved (2026-10-06)
Source: PRD "New look for UngradedMinds (proposed spec 017)" by @Happiness, 2026-10-06, pasted by the owner. Design: the canvas "Ungraded Minds – Desktop Flow" (14 screens and a component sheet). Changes how screens look in 001, 003, 007, 008, 009, 011, 012, 015 and 016; changes no behaviour
Last Updated: 2026-10-06

Overview

The app works, but it doesn't yet look or sound like the product in the new designs: a warm companion for Indian students, not a developer tool. This spec gives every screen the app has today the look from the designs: colours, type, shapes, buttons, cards, trust labels, dialogs, messages, drawings, the logo and the name "Ungraded Minds".

It changes how the app looks, not what it does. Anything the designs show that the app can't do today stays out (see Out of Scope); each of those needs its own spec.

Business Context

Goals

Non-Goals / Out of Scope

Design elements the app has no behaviour for stay out, even where a mock-up shows them:

Shown in the designsWhy it is out
Choosing a goal and a decide-by date; the pinned goal strip; Edit goal warningThe app has projects with a description, not goals *Partly superseded by 020 FR-001 and FR-006 (2026-10-06): goals, with an optional decide-by date, are now chosen on the New goal form and listed in My Goals; the pinned goal strip stays out.*
Date of birth, class, board and state fields on About youThe details form asks for name, location, age and educational background (D-007) *Superseded by 020 FR-018 (2026-10-06): onboarding step 1 now asks for the year of birth (not a full date of birth), class, board and state, among other fields.*
Tab bar with Discover, Decide and Act; tab states (done, outdated)A chat is one page in time order with a section index (011)
Evaluate, Compare, Choose and Next steps screensNo such steps exist
Home with My Journey and the journey bar; a rail with Home and My JourneyNo such screens exist (D-003)
Ask drawerThere is no free chat after the options exist (product boundaries)
Tappable answer chips and "Question 4 of about 8"Questions are free text with no set count today (D-005) *Partly superseded by 025 FR-001 (2026-10-07): questions now come with suggested-answer chips; the question counter stays out.*
Class 8–9 version with softer copy and brighter tilesThe app has no age-based version *Partly superseded by 020 FR-018 (2026-10-06): "Class 8–9" is now a choice on onboarding step 1; the softer copy and brighter tiles stay out.*
Toast messages such as "Added to shortlist"New feedback the app doesn't give today (D-004)
Options as a two-column gridOptions show one card at a time in a viewer (012, D-001)
Icons for projects and chats in the collapsed sidebarThe thin strip holds only the expand button and the reminders-due count (011 FR-013, D-003) *Partly superseded by 021 FR-006 (2026-10-07): the strip has one icon per menu entry, including My Goals; still no icon per goal or journey.*

Also out:

User Stories

US-001: A warm, consistent app

As a student I want every screen to look warm and consistent So that the app feels like a companion that shows me the path

Acceptance Criteria:

US-002: Trust at a glance

As a student I want each source on an option to show clearly how far it can be trusted So that I can judge a claim at a glance

Acceptance Criteria:

US-003: Marks I can scan

As a student I want my mark on each option to be obvious from its colour and label So that I can scan my list quickly

Acceptance Criteria:

US-004: Calm progress and errors

As a student I want to see what the app is doing during research, and what I can do if it fails, in calm, plain words So that a failure doesn't feel alarming

Acceptance Criteria:

US-005: Safe dialogs

As a student I want dialogs to say what will happen and make the safe choice easy to find So that I never lose anything by accident

Acceptance Criteria:

US-006: Readable and keyboard-friendly

As a student I want text I can read comfortably and controls I can reach with the keyboard So that the app works for me however I use it

Acceptance Criteria:

US-007: A list of differences

As the owner I want a list of every difference between a screen and its design So that I can approve the look by reading this document

Acceptance Criteria:

Functional Requirements

Exact colours, sizes and spacing come from the designs' component sheet. These requirements say what must be true.

Name, logo and tone

FR-001: The name "Ungraded Minds" — Partly superseded by 020 FR-017 and 029 FR-006

Partly superseded by 029 FR-006 (2026-10-08) (029-first-run-and-brand-polish): the name is written in the app's heading font (not a handwritten script), a little bigger, with "Un" in blue. The words and where the name appears are unchanged.
Partly superseded by 020 FR-017 (2026-10-06): the first-run details screen is now onboarding step 1, Tell us about you, which is also shown once as Update your details to students whose details were saved in the old form (020-my-goals-onboarding). The original text is kept below for history.

THE SYSTEM SHALL show the name as two words, Ungraded Minds, in the browser tab title, the sidebar header, the start screen and the first-run details screen.

Documents, the README and package names keep their names, as in 011 D-004.

*Replaces the one-word "UngradedMinds" in 011 FR-015.*

FR-002: The logo — Partly superseded by 020 FR-017, 029 FR-006 and 037 FR-002

Partly superseded by 037 FR-002 (2026-10-10) (037-basecamp-and-sidebar-polish): there is no separate start screen any more. The app opens on Basecamp, which shows the logo as its title, with the line and + New goal, only when there are no goals.
Partly superseded by 029 FR-006 (2026-10-08) (029-first-run-and-brand-polish): the name beside the heart is in the heading font with "Un" in blue, not "a rounded handwritten script"; in the sidebar the heart is slightly smaller so the name fits.
Partly superseded by 020 FR-017 (2026-10-06): the first-run details screen is now onboarding step 1 (also shown once as Update your details); the logo has its line "Your future isn't a grade." there only, not on step 2 (020-my-goals-onboarding). The original text is kept below for history.

THE SYSTEM SHALL show the logo from the designs: a blue heart with a green and an orange figure, with the name in a rounded handwritten script:

FR-003: One tagline, in one place — Partly superseded by 020 FR-017

Partly superseded by 020 FR-017 (2026-10-06): the first-run logo lockup is on onboarding step 1 and on the one-time Update your details screen, and not on step 2 (020-my-goals-onboarding). The original text is kept below for history.

THE SYSTEM SHALL show "Your future isn't a grade." only in the first-run logo lockup, and no other tagline anywhere.

The start screen keeps its description line "Get researched recommendations for what you want to achieve." (003); it is a description, not a tagline.

FR-004: Speaking to the student — Must Have

THE SYSTEM SHALL address the student as "you" and "your" in every text meant for them, never in a parent's voice, and never use the name "Mera Bachha".

*Today's texts already meet this; the rule keeps it so.*

FR-005: No scores or rankings — Must Have

THE SYSTEM SHALL show nothing as a score, rank, winner or comparison with other students.

The levels (Easy, Medium, Hard, Not fit) stay, shown as plain labels: one neutral style, none of them red, Not fit in neutral grey (D-002).

Colour, type and shape

FR-006: Background and cards — Must Have

THE SYSTEM SHALL show pages on a pale blue-white background, and cards in white with rounded corners and soft, low-contrast shadows.

FR-007: Type — Partly superseded by 029 FR-006

Partly superseded by 029 FR-006 and D-005 (2026-10-08) (029-first-run-and-brand-polish): the handwritten script is used only for short encouraging lines; the logo's name is in the heading font.

THE SYSTEM SHALL show headings in deep navy in a bold, rounded sans-serif, and body text in slate. A handwritten script is used only for the logo and short encouraging lines (the logo line and the first-run note, FR-019).

FR-008: Accent colours — Must Have

THE SYSTEM SHALL use royal blue for main actions and links. Pastel tiles (mint, sky, peach, lavender, blush, teal) carry a matching, stronger icon colour.

FR-009: Icons — Must Have

THE SYSTEM SHALL use simple line icons with one consistent line weight wherever the app shows a symbol today (expand and collapse, close ×, the viewer's ‹ ›), and for the drawings in FR-029.

FR-010: Text size — Must Have

THE SYSTEM SHALL show body text at 16px or larger on every screen, and no label, badge or count below 13px.

*Today, badges, the reminders count and section headings are 12–12.8px; they grow to at least 13px. 012 FR-007's 16px base stays.*

Controls and feedback

FR-011: Buttons — Must Have

THE SYSTEM SHALL show:

Each form, dialog and picker has one main button. The Reset button in the corner stays quieter than the main actions (016 NFR-001).

FR-012: Hover and focus — Must Have

THE SYSTEM SHALL give every control a hover look and a clear keyboard-focus ring. A control that shows only an icon shows its name on hover, and screen readers hear that name.

FR-013: Fields and chips — Must Have

THE SYSTEM SHALL give text fields and choice chips (the rule-out quick picks, the reminder quick picks, the level tabs) one shared rounded look. A chosen chip is filled blue.

FR-014: Cut-off names — Must Have

THE SYSTEM SHALL keep cutting long names off with "…" and showing the full name on hover, as today (001 FR-028).

Layout

FR-015: The top of the screen — Must Have

THE SYSTEM SHALL keep today's layout at the top: no top bar, the logo in the sidebar header, and Reset floating in the top right corner of the main area (016 FR-001, 016 design TD-005). The chat's "<project> / <chat>" line stays at the top of the chat (001 FR-010). The student's name is not shown (D-013).

FR-016: The sidebar — Partly superseded by 021 FR-001 and FR-006, by 036 FR-007 and by 037 FR-008

Partly superseded by 037 FR-008 (2026-10-10) (037-basecamp-and-sidebar-polish): the sidebar and the strip are light grey (#eceff3), not white; the open item stays soft blue.
Partly superseded by 021 FR-001 and FR-006 (2026-10-07) (021-sidebar-menu): the sidebar's items and order are now the menu My Details, My Goals (with the goals), Reminders, Settings, with Reminders and Settings pinned at the bottom; the 72px strip holds Expand and the four menu icons. The 260px width, white surface and soft blue open item stay. The original text is kept below for history.
Partly superseded by 036 FR-007 (2026-10-09) (036-compact-stepper-sidebar-summary): the open sidebar is no longer 260px; it is about 272px at a 1,280px window, growing to about 304px on large windows. The 72px strip, the white surface and the soft blue open item stay. Goal and journey rows now carry a small symbol (036 FR-008, FR-009).

THE SYSTEM SHALL keep the sidebar's items, order and behaviour, at 260px wide when open. It is white, and the open item is soft blue.

WHEN the sidebar is collapsed THE SYSTEM SHALL show a slim strip 72px wide (today 44px) holding the same things as today: the Expand sidebar button and the reminders-due count (011 FR-013, D-003).

FR-017: Page width — Must Have

THE SYSTEM SHALL keep the chat's contents centred at up to 1,100px wide (012 FR-006), and centre the other pages (a project, General, New project, Reminders due) at up to 880px (D-014). The chat's section index stays next to the scrollbar, restyled.

FR-018: Desktop and laptop only — Must Have

THE SYSTEM SHALL be designed for windows 1,280–1,920px wide. This spec adds no mobile layout.

Screens

FR-019: First-run details screen — Superseded by 020 FR-013 to FR-018 and FR-023

Superseded by 020 FR-013 to FR-018 and FR-023 (2026-10-06): the first run has two steps, Tell us about you and What would you like help with?, with a thin progress bar and "Step 1 of 2" or "Step 2 of 2", new fields on step 1 and Next instead of Continue, and a handwritten note on each step's illustration panel; Your details (formerly General) shows step 1's fields without the panel (020-my-goals-onboarding). The original text is kept below for history.

WHEN the first-run details form is shown THE SYSTEM SHALL show two columns:

There is no progress bar, because the form has one step. General shows the same fields in the new card and field look, without the illustration.

FR-020: Questions — Must Have

THE SYSTEM SHALL show the AI's questions (Discovery and rounds) as white speech bubbles on the left, and the student's answers as blue bubbles on the right. The latest question, while it waits for an answer, sits in a highlighted card.

The message box keeps its place at the bottom (012 FR-008) and its behaviour. AI text that isn't a question (the recommendation text of older chats, the round's closing line) is not put in a bubble.

*Changes the look in 001 FR-024 (the AI's replies were unboxed).*

FR-021: Research while it runs — Must Have

WHILE research runs THE SYSTEM SHALL show, in the new look, what it shows today: the stage, each search on its own line, and the sources each search found (title and link). A finished run looks the same when the student comes back. Nothing re-runs.

The research list shows no trust labels (D-009).

FR-022: Errors and warnings — Must Have

IF a model, research or button error happens THE SYSTEM SHALL show it in the soft coral palette, in the same place, with the same words ("Model error: …", "Research error: …", "Couldn't save: …") and the same Retry or Dismiss as today: the banner at the top of the main area as a calm card, the error under an option card as a calm line. Field errors on forms use the same coral.

The Opik tracing warning (002) and the in-app reminder alert (009) keep their words and buttons, shown as soft peach cards so they stay distinct from errors.

*Replaces "red" in 001 FR-025, 003 FR-016, 005 FR-008, 008 FR-024 and the error notes of 007 and 009.*

FR-023: The option card — Must Have

THE SYSTEM SHALL show each option card with what it shows today, in the new card look: its name, its level and level reason (if it has one), what it is, why it fits (or "Why it might look right" for Not fit), pros, cons, rough cost, sources with trust labels, the mark buttons and Remind. The badges New and Updated and the label "from earlier research" are small pills.

AI's suggestion stays a line above the cards, on a lavender tile, with its wording unchanged.

FR-024: Marks — Must Have

THE SYSTEM SHALL show:

One mark per option, and pressing the chosen one clears it, as today (007). Ruled-out cards stay in the collapsed "Ruled out (N)" group, as today.

FR-025: Rule-out reason, groups and viewer — Must Have

THE SYSTEM SHALL keep the rule-out reason picker, the groups "From earlier research (N)" and "Ruled out (N)", Options at a glance, the level tabs and the options viewer (arrows, dots, "2 of 4") working exactly as today, in the new look (D-001).

FR-026: Trust labels — Must Have

THE SYSTEM SHALL show each source on an option card with its site as a link and a colour-coded trust label that writes out its tier:

LabelColour
Tier 1 officialgreen
Tier 2 newsblue
Tier 3 aggregator or coachingamber
Tier 3 likely official, unverifiedamber
Tier 4 forum or bloggrey
Tier 4 unknown or uncertaingrey

A legend that explains the four colours is shown once in each Options section.

No source can be tier 1 until the known list of official sites exists (006), so green won't appear yet.

*Changes the wording in 007 FR-015 (the tier number is added).*

FR-027: Reminders — Must Have

THE SYSTEM SHALL show Remind, the reminder picker, the "Reminder: …" line with Change and Cancel, and the Reminders due page with Open and Dismiss, in the shared button and card look. The reminders-due count in the sidebar and the strip is orange, with the number written as today.

FR-028: Confirmations — Must Have

WHEN the Reset box is shown THE SYSTEM SHALL show it as a centred white card over a dimmed page, with its title, its sentence with the counts, Cancel first (and focused), and Reset everything in coral as the dangerous choice (016 NFR-001, D-008). Its words stay as in 016.

THE SYSTEM SHALL show the match confirmation in the same card look, in its place inside the Research section (D-010).

THE SYSTEM SHALL show the other confirmations (delete a project, rename a chat, delete a chat, discard new research) as app dialogs in the same look as the Reset box, with today's words, today's choices and the safe choice first (D-015).

FR-029: Empty and loading states — Must Have

THE SYSTEM SHALL show the empty states (the start screen with no project open, "No chats yet.", "No reminders due.") with today's line and one small drawing (a sun, a sprout or hills), used sparingly. Loading lines ("Loading…", "Thinking…", "Researching…", "Saving recommendation…" and the others) keep their words, in the new type.

FR-030: Behaviour is unchanged — Partly superseded by 020 FR-012

Partly superseded by 020 FR-012 (2026-10-06): the words on screen listed in 020 FR-012 changed too: project becomes goal, chat becomes journey, New chat becomes New journey and General becomes Your details; behaviour is still unchanged by this spec (020-my-goals-onboarding). The original text is kept below for history.

THE SYSTEM SHALL keep what every control does, what is saved, and what leaves the machine exactly as the earlier specs say. Words on screen stay as they are, except where FR-001, FR-002 and FR-026 change them (D-011).

Non-Functional Requirements

NFR-001: Privacy

NFR-002: Readability

NFR-003: Keyboard and accessibility

NFR-004: Longer text

NFR-005: Window size

NFR-006: Simplicity

NFR-007: Speed

NFR-008: Theme

User Experience Notes

Screens and their closest design (canvas screen numbers; "—" means the component sheet sets the look):

Today's screenClosest designWhat changes (look only)
First-run details form1 About youTwo columns, logo lockup, illustration panel, rounded fields (FR-019). Fields stay as today (D-007)
General1 About you (form card only)Card and field look (FR-019)
Start screen (no project open)—Logo as title, today's line and button, a drawing (FR-002, FR-029)
Sidebar with projects, chats, Reminders dueLeft railWhite surface, soft blue open item, 72px collapsed strip with today's contents (FR-016)
Project page, chat list, New project—Card look, 880px width, empty-state drawing (FR-017, FR-029)
Chat: Questions and rounds3 QuestionsSpeech bubbles, highlighted current question (FR-020)
Chat: live and saved research5 ResearchStage, search lines, sources; no trust labels (FR-021)
Chat: AI's suggestion, Options at a glance, level tabs, cards, viewer6 OptionsCard, badges, plain level labels, mark colours, lavender suggestion tile, trust legend (FR-023–FR-026)
Rule-out reason picker6 reason panelSame inputs, new chips and buttons (FR-013, FR-025)
Message box, Research again, Go to options, Add more about me6 hint bannerField and pill buttons (FR-011, FR-013)
Match confirmation4 Confirm dialog (card look only)Card look, stays inline (FR-028, D-010)
Reset4 Confirm dialogDimmed page, counts kept, coral Reset everything (FR-028)
Delete project, rename chat, delete chat, discard research4 Confirm dialogApp dialogs instead of the browser's boxes (FR-028, D-015)
Remind, reminder picker, Reminders due—Shared buttons, chips and cards; orange count (FR-027)
Error banner, error under a card, field errors5 error statesSoft coral (FR-022)
Opik warning, in-app reminder alert—Soft peach card (FR-022)
Trust labels on option sourcesComponent sheet, tier legendSix coloured labels with the tier written out, plus a legend (FR-026)

Known differences from the designs, beyond Out of Scope: the chat column is 1,100px, not 880px (D-014); there is no top bar and no name on the right (D-013); level labels and tabs, which the designs don't have, are shown (D-002).

Constraints

Decisions

The PRD was written on a recommended default for each place where the designs and the app disagree. D-001–D-008 record those defaults (PRD decisions 1–8); D-009–D-011 come from checking the PRD against the specs and the code; D-012–D-015 are the owner's answers to Q-001–Q-004. Approving these requirements confirms D-001–D-011.

D-001: Keep the one-card-at-a-time viewer

Decision: Options stay in 012's viewer; only the cards are restyled. Reason: A two-column grid changes how options are browsed and needs its own spec. Source: PRD decision 1 Impacts: FR-025, Out of Scope

D-002: Levels stay, as plain labels

Decision: Easy, Medium, Hard and Not fit, Options at a glance and the level tabs stay. Level labels use one neutral style; none is red (today Hard is red and Medium amber). Not fit is neutral grey. Reason: Colour on levels can read as good and bad, which FR-005 forbids. Removing levels would be a behaviour change. Source: PRD decision 2 Impacts: FR-005, FR-023, FR-025

D-003: Keep the sidebar; the collapsed strip is 72px with today's contents — Partly superseded by 021 FR-001 and FR-006 (the items, order and strip contents; the 72px width stays)

Decision: The sidebar keeps its items and behaviour. Collapsed, it is 72px wide, matching the designs' rail, and holds only the expand button and the reminders-due count. Reason: A real rail (Home, My Journey, icons for projects and chats) needs a new way to reach projects and chats. Source: PRD decision 3; the strip's contents from 011 FR-013 Impacts: FR-016, Out of Scope

D-004: No toasts

Decision: No "Added to shortlist" or similar messages. Reason: The card already shows the mark; a toast is new feedback. Source: PRD decision 4 Impacts: Out of Scope

D-005: No answer chips, no question counter — Partly superseded by 025 FR-001

Partly superseded by 025 FR-001 (2026-10-07): answer chips now exist (suggested answers under each question, 025-answer-suggestions); the question counter stays out. The original text is kept below for history.

Decision: Both stay out. Reason: Today's questions are free text and the AI asks a varying number (1–5), so neither exists to restyle. Source: PRD decision 5, checked against today's app Impacts: Out of Scope, FR-020

D-006: Fonts ship with the app

Decision: The two design fonts, the icons and the drawings are files inside the app, not loaded from the web. The design records this as a technical decision. Reason: Loading web fonts would send a request to an outside service, which the privacy rules don't allow. Source: PRD decision 6 Impacts: NFR-001, NFR-006, Constraints

D-007: Keep today's details fields

Decision: The details form keeps name, location, age and educational background. *Superseded by 020 FR-018 (2026-10-06): the details are now first name, year of birth, where the student is, board and stream (or what they study), state and city.* Reason: The designs' date of birth, class, board and state would change what is collected and saved. Source: PRD decision 7 Impacts: FR-019, Out of Scope

D-008: Reset everything in coral

Decision: Reset everything is coral. Reason: 016 NFR-001 already asks for it to look dangerous; coral is that style in the new palette. Not an addition. Source: PRD decision 8 Impacts: FR-028

D-009: No trust labels in the research list

Decision: The research list shows sources as today, without trust labels. Option cards show them. Reason: Adding them would reverse 007 D-008 and add information to a screen, which is a behaviour change. The PRD's FR-021 asked for them. Source: Check against 007 D-008 Impacts: FR-021, US-002, Out of Scope

D-010: The match confirmation stays inline

Decision: It keeps its place at the end of the Research section, in the dialog card look, not as a pop-up over a dimmed page. Reason: 008 FR-020, 011 FR-005 and 012 keep it an inline list; a pop-up changes where it appears and how the page scrolls. Source: Check against 008, 011 and 012 Impacts: FR-028

D-011: Today's wording stays

Decision: Every text on screen stays word for word, except the name (FR-001), the logo line (FR-002) and the tier number in trust labels (FR-026). *Partly superseded by 020 FR-012 (2026-10-06): the texts in 020 FR-012 changed: project becomes goal, chat becomes journey, New chat becomes New journey and General becomes Your details.* Reason: Earlier specs fix many texts ("No chats yet.", "Thinking…", "Reset everything?", …). Rewording each would need its own list; the PRD names no new texts. Source: Check against 001–016 Impacts: FR-029, FR-030

D-012: Light only

Decision: The app has one light look, whatever the computer's light or dark setting. Reason: The designs define only a light look; a dark version would have nothing to be checked against. Source: Q-001 (owner, 2026-10-06) Impacts: NFR-008; supersedes the theme part of 001 FR-032

D-013: No top bar

Decision: No top bar. The logo stays in the sidebar, Reset floats in the top right corner as today, and the student's name isn't shown. Reason: Keeps the owner's choice in 016 (design TD-005). Source: Q-002 (owner, 2026-10-06) Impacts: FR-015, UX Notes

D-014: The chat stays 1,100px wide

Decision: The chat's column stays up to 1,100px (012 FR-006). The other pages use the designs' 880px. Reason: The wide chat was the owner's request in 012. Source: Q-003 (owner, 2026-10-06) Impacts: FR-017, UX Notes

D-015: App dialogs replace the browser's boxes

Decision: Deleting a project, renaming a chat, deleting a chat and discarding new research use app dialogs in the Reset box's look, with today's words and choices. Reason: The browser's boxes can't be restyled; the app already has one such dialog. Source: Q-004 (owner, 2026-10-06) Impacts: FR-028, NFR-003, UX Notes; the look of 001 FR-007, FR-013 and FR-014

Questions

Q-001: Does the app keep a dark theme?

Status: answered Answer: Light only. Decision: D-012

Q-002: Is there a top bar?

Status: answered Answer: No top bar; Reset floats top right as today. Decision: D-013

Q-003: How wide is the chat?

Status: answered Answer: Keep 1,100px for the chat; other pages 880px. Decision: D-014

Q-004: What happens to the browser's own boxes?

Status: answered Answer: App dialogs in the new look. Decision: D-015

Superseded Baseline (to Mark at Review, P-001)

Look and wording only; no behaviour is superseded.

Success Metrics

MetricTarget / SignalNotes
Matches the designsEvery screen in the UX Notes table, opened at 1,440px and 1,280px, differs from its design only where this document saysBrowser check next to the canvas. A difference not listed is reported, not fixed silently (P-002)
ControlsEvery control tried with the mouse and the keyboard; hover and focus looks seenBrowser check
Nothing lostA run from the first-run form through questions, research and options, to marks, a reminder, Research again with a match confirmation, a project and chat delete, and Reset, behaves as beforeOn a throwaway copy of the data
Long textText 30–40% longer on cards, buttons and dialogs holdsBrowser check
No outside requestsThe browser's network list shows no request to any new outside serviceNFR-001
BuildBuild and lint pass

Risks and Mitigations

RiskImpactMitigation
A look change quietly alters behaviourHighFR-030 and the full-run check
Features the designs imply creep inMediumOut of Scope; the report-not-fix rule (P-002)
Amber and pastel colours are hard to read; amber means parked, tier 3 and a due reminderMediumNFR-002: a contrast check on every label, and every state written as a word
The designs are static, so states such as hover are drawn only on the component sheetLowThe component sheet is the reference for those states
The canvas files, fonts or drawings aren't available, or can't be shippedMediumConstraints: exported and licence-checked before design

Glossary

Deep Research togglereview:done033-deep-research-toggle
Status: Draft (requirements)
Source: Owner's request, 2026-10-08: "I want to add a Deep Research toggle in Settings. If on it will use Perplexity Agent API to do both research and use it's own web search. When this setting is on the Research and Web Search dropdowns should be disabled."
Last Updated: 2026-10-08

Overview

Today research uses the chosen Research model plus Web Search service. This spec adds a Deep Research toggle on Settings. When on, research is handed to the Perplexity Agent API, which runs its own web searches and returns a reasoned answer with citations. The local Research model and Web Search choices are not used, so their dropdowns are disabled.

Deep Research is off by default.

Business Context

Goals

Non-Goals / Out of Scope

User Stories

US-001: Turn on Deep Research

As the owner I want a Deep Research toggle on Settings So that I can switch research to Perplexity

Acceptance Criteria:

US-002: Research with Deep Research on

As the owner I want research to use Perplexity Agent API when Deep Research is on So that Perplexity handles reasoning and web search

Acceptance Criteria:

US-003: Disabled dropdowns when Deep Research is on

As the owner I want Research model and Web Search dropdowns disabled when Deep Research is on So that it's clear those choices don't apply

Acceptance Criteria:

Functional Requirements

FR-001: Deep Research toggle — Must Have — Partly superseded by 038 FR-010

Partly superseded by 038 FR-010 (2026-10-10) (038-new-logo-path-cards-panels): with no saved choice, and after a Reset, the toggle is on when PERPLEXITY_API_KEY is set and off without it. Its place and saving are unchanged. The original text is kept below for history.

THE SYSTEM SHALL show a Deep Research toggle on the Settings page, below the Web Search choice and above Reflections.

THE SYSTEM SHALL set the toggle to off by default and after a Reset.

FR-002: Deep Research requires Perplexity — Must Have

IF PERPLEXITY_API_KEY is not set in the settings file THEN the Deep Research toggle SHALL be disabled, with a hint saying "Add a Perplexity key and restart the backend to use Deep Research."

IF the owner tries to turn Deep Research on via the API while the key is missing THEN the system SHALL return 422.

FR-003: Research uses Perplexity when Deep Research is on — Must Have

WHEN Deep Research is on THE SYSTEM SHALL send the research task to the Perplexity Agent API (POST https://api.perplexity.ai/v1/responses) with model perplexity/sonar (or PERPLEXITY_MODEL) and tools: [{"type": "web_search"}].

THE SYSTEM SHALL include the same context the local Research model receives: student details, goal, discovery answers, and marks/reasons from Research again.

THE SYSTEM SHALL NOT call the local Research model or the web_search tool during the research step when Deep Research is on.

FR-004: Parsing Perplexity Deep Research output — Must Have

THE SYSTEM SHALL parse Perplexity's response into:

THE SYSTEM SHALL save the options, top pick and sources the same way as today's research output (spec 005).

FR-005: Disable Research and Web Search dropdowns — Must Have

WHEN Deep Research is on THE SYSTEM SHALL disable the Research model dropdown and the Web Search dropdown on the Settings page.

THE SYSTEM SHALL still return their current saved values in GET /api/settings so the page can display them.

FR-006: Turning Deep Research off — Must Have

WHEN the owner turns Deep Research off THE SYSTEM SHALL save it immediately and use the local Research model + Web Search choice for the next research turn.

FR-007: Persistence — Must Have — Partly superseded by 038 FR-010

Partly superseded by 038 FR-010 (2026-10-10) (038-new-logo-path-cards-panels): a Reset puts Deep Research back to its default, on when the key is set. A saved choice is still kept across restarts and releases.

THE SYSTEM SHALL keep the Deep Research setting across restarts and releases, and a Reset SHALL put it back to off.

Non-Functional Requirements

NFR-001: Reliability

Switching Deep Research on or off never loses saved journeys, answers, options, marks or reminders.

NFR-002: Usability and accessibility

NFR-003: Configuration

The settings template and README explain Deep Research, that it needs PERPLEXITY_API_KEY, and that it disables the Research model and Web Search choices.

Constraints

Decisions

D-001: Deep Research is off by default — Superseded by 038 D-008

Superseded by 038 D-008 (2026-10-10) (038-new-logo-path-cards-panels): on by default when the key is set, unless the owner saved "off".

Decision: The toggle starts off and Reset turns it off. Reason: Preserves today's behavior; opt-in feature. Impacts: FR-001, FR-006, FR-007.

D-002: Deep Research uses Perplexity Agent API

Decision: When on, research is sent to https://api.perplexity.ai/v1/responses with the web_search tool. Reason: Perplexity can search and reason in one call. Impacts: FR-003, FR-004.

D-003: Dropdowns disabled, not hidden

Decision: Research and Web Search dropdowns stay visible but disabled when Deep Research is on. Reason: The owner sees what values will apply when Deep Research is off. Impacts: FR-005, US-003.

D-004: No automatic fallback

Decision: If Perplexity fails, the run fails with the usual error card and Retry. Reason: Avoids silently switching research strategy. Impacts: Out of Scope, NFR-001.

Questions

Q-001: Should Deep Research affect Discovery?

Status: open Question: Should Deep Research also disable web_search during Discovery, or only the final research step? Leaning: Only the final research step.

Q-002: How to parse Perplexity's answer into options?

Status: open Question: Perplexity returns text + citations. Should the prompt request JSON, or should a second model call extract options? Leaning: Request JSON from Perplexity; fall back to structured extraction if JSON fails.

Superseded Baseline (to mark at review, P-001)

Success Metrics

MetricTarget
ToggleDeep Research toggle appears, saves, survives restart, Reset restores off
Disabled dropdownsResearch and Web Search dropdowns disabled when on, enabled when off
Deep researchWith toggle on and Perplexity key set, a full research turn returns options with sources
Off modeWith toggle off, behavior identical to before this spec

Risks and Mitigations

RiskImpactMitigation
Parsing Perplexity's answer into options is unreliableHighRequest JSON output; validate; fallback to extraction
Perplexity Deep Research is slower or more expensiveMediumOpt-in toggle
Disabling dropdowns confuses usersLowShow helper text under the toggle

Glossary

Backlog — candidates

F01 Reject blank names and titles in the API backend
Goal names are now derived (about.goal_name), but the API still saves a journey title of only spaces as blank (the UI blocks it, ConfirmDialog.tsx). Only the residual journey-title case is left
F02 Limit the history sent to the model backend
Every message of a journey goes into the prompt on each turn (main.py, advisor.py); very long journeys can exceed the model's limit. Only the shared Compass conversation is capped (last 20 rows, 041 FR-013)
F03 Automated tests both
Behavior is checked by hand only; tech-stack.md says "Test — none yet"
F12 Research survives search-service limits backend
A Firecrawl rate limit (~10 searches/min on the owner's plan) or one failed search switches search off for the rest of the run (013 Issue 1, 008 Issue 3, 003 D-020)
F13 One action at a time both
Two simultaneous presses are both applied where the design says the second gets 409 (007 Issue 1, 009 Issue 3); a second Compass run can start at the same time (041 follow-up)
F14 Trust tiers a person can check both
Tier 1 only comes from a known official-site list that was never built (006 FR-002), and the sites Jev was unsure about queue for a review screen that has no UI yet (006)
F15 Tracing matches the runs backend
One research turn produced far more Opik traces than turns; the count per turn was never confirmed (005 review Issue 1)
F16 Privacy and consent before other students use the app both
Only the owner is signed in today. Details of students who may be 9–14 would go to model providers, the search service and Opik (020 D-013, product.md risk)
F17 Keep the hosted copy in step with main ops
014's hosted checks, 018's rollout, 019's hosted checks and 028's fixes are outstanding; the hosted copy has no PERPLEXITY_API_KEY, so Deep Research stays off there (038)
F19 Deep Research keeps its sources backend
033's review (2026-10-12) found that with Deep Research on — the default whenever PERPLEXITY_API_KEY is set (038 FR-010) — a run saves its options with no sources: the research branch empties the run's evidence and never refills it, while Perplexity's own citations are discarded. Deep Research itself is shipped; this is its fix, and it should land before the next hosted release
F04 Goal files both
Upload documents (PDF, text, Markdown) to a goal and let the AI use them
F05 Stop button both
Stop a streaming reply and keep the text written so far; today only leaving the page cancels a turn
F06 An address for every page frontend
Journeys have addresses and reload/Back work (018 FR-006, 034); goals, My Goals, Me & My Compass, Reminders and Settings have none (021, out of scope)
F07 Rename/delete a journey where you are frontend
Rename and Delete exist only on the goal page's journey list (GoalView.tsx)
F08 Model per goal both
The Thinking and Research models are global (019, 030)
F09 Edit and regenerate both
Only Retry of a failed or interrupted turn exists (003 FR-016)
F10 Search across journeys both
No search UI or endpoint; "Search" in the specs means the web-search service
F11 Copy button frontend
Replies and code blocks render as Markdown with no copy control
F18 Accessibility pass frontend
VoiceOver was never run on the guided flow or the Compass conversation (034, 039, 041 follow-ups)

Shipped

001 AI Projects core app
002 Opik tracing
003 Guided recommendations
004 Project name in the decision context
005 Structured recommendations with saved options and evidence
006 Source trust tiers for unknown sites
007 Option marks with buttons, routed without AI
008 Moving between steps and Research again
009 Option reminders and four options per research
010 Empty web searches don't fail the research
011 One-page chats, section index, collapsible sidebar, name UngradedMinds
012 Swipeable options and wider chat
013 DeepSeek model, Firecrawl search
015 Six options with levels
016 Reset button
020 My Goals and onboarding
021 Sidebar menu
022 Fold the goal list under My Goals
023 More than one email can sign in
024 A "Class 5–7" choice for "I'm in…"
025 Suggested answers as buttons
026 Question tone
027 Questions survive a broken or combined reply
028 Three ways to begin Your story
029 First-run and brand polish
030 OpenCode Go models
031 Exa default search + Settings dropdown
032 Perplexity search service
034 Summit and Compass on tabs, trail-shaped stepper
035 Question settings for each path
036 A compact stepper, wider sidebar, clearer summary
037 Basecamp and a polished sidebar
038 New logo, path cards, Summit/Compass panels
039 Family view (dev and preview builds only)
040 Basecamp welcome
041 Welcome tips + Me & My Compass
042 Me & My Compass order and names