@@ -154,47 +154,89 @@ flowchart TD
154154
155155## Decision
156156
157- We ship ** Candidate D, blended with one ergonomic touch from C** .
157+ We ship ** Candidate D, blended with the consent-gated ergonomics of C** .
158158
159159- ** From D** : two-script split (` install.sh ` , ` run.sh ` ); we * detect*
160- Ollama rather than installing it; we never start daemons in
161- ` install.sh ` ; the run-time server still launches if Ollama is down so
162- the UI is usable and the failure is observable in the chat panel.
163- - ** From C** : in ` install.sh ` , if Ollama * is * present, we offer to
164- ` ollama pull ` the default model on the user's behalf — gated by
165- ` TUTOR_SKIP_MODEL_PULL ` and skippable in CI. Pulling a model the user
166- already chose to have Ollama for is low-risk and saves a step .
160+ Ollama and the model rather than installing them silently; the
161+ run-time server still launches if Ollama is down so the UI is usable
162+ and the failure is observable in the chat panel.
163+ - ** From C** : when something host-level is missing — the Ollama binary,
164+ the ` ollama serve ` daemon, or the default model — ` install.sh `
165+ * offers * to handle it. The user types ` y ` to accept. The default
166+ answer is ** no ** , so pressing Enter never installs a system binary .
167167
168168This blend has:
169169
170170- 2 commands typed (` ./install.sh ` , ` ./run.sh ` ) — same as B/D/E.
171- - Zero hidden system-level installs.
172- - One actionable error message if Ollama is missing (we print the
173- install command for the user's platform).
171+ - Zero hidden system-level installs. Every system-touching action is
172+ preceded by an explicit y/N confirmation.
173+ - A single non-interactive entry-point for CI
174+ (` TUTOR_NONINTERACTIVE=1 ` defaults all prompts to "no";
175+ ` PYTHON_TUTOR_ASSUME_YES=1 ` defaults them to "yes" for pre-approved
176+ unattended setup).
174177- A web UI that loads even when the LLM is unreachable — so the learner
175178 always gets * something* to interact with.
176179
180+ ``` mermaid
181+ flowchart TD
182+ Clone[git clone repo] --> Install[./install.sh]
183+ Install --> Py[Python 3.10+ check]
184+ Py --> Venv[Create / reuse backend/.venv]
185+ Venv --> Pip[pip install backend deps]
186+ Pip --> HasOllama{ollama on PATH?}
187+ HasOllama -- no --> AskInstall{Install Ollama now? y/N}
188+ AskInstall -- y --> RunInstaller[Run upstream installer]
189+ AskInstall -- N --> HintInstall[Print manual install hint]
190+ RunInstaller --> Daemon{Daemon on :11434?}
191+ HasOllama -- yes --> Daemon
192+ HintInstall --> NextBanner
193+ Daemon -- yes --> Model{Model present?}
194+ Daemon -- no --> AskStart{Start 'ollama serve' now? y/N}
195+ AskStart -- y --> Spawn[nohup ollama serve & probe up to 10s]
196+ AskStart -- N --> HintStart[Print 'run: ollama serve' hint]
197+ Spawn --> Model
198+ HintStart --> NextBanner
199+ Model -- yes --> NextBanner
200+ Model -- no --> AskPull{"Pull model? y/N"}
201+ AskPull -- y --> Pull[ollama pull TUTOR_MODEL]
202+ AskPull -- N --> HintPull[Print 'ollama pull' hint]
203+ Pull --> NextBanner
204+ HintPull --> NextBanner
205+ NextBanner --> AskLaunch{Launch ./run.sh? y/N}
206+ AskLaunch -- y --> Run[./run.sh → uvicorn]
207+ AskLaunch -- N --> Done[Print next-step banner]
208+ Run --> Browser[Open http://localhost:8001]
209+ ```
210+
177211## How the scripts behave
178212
179213### ` install.sh `
180214
1812151 . Detect Python ≥3.10. If missing or too old, print install command,
182216 exit 1.
1832172 . Create ` backend/.venv ` if it doesn't exist; otherwise reuse it.
184- 3 . ` pip install -r backend/requirements-dev.txt ` (idempotent).
185- 4 . Check ` ollama ` on ` PATH ` . If missing, print install command and exit
186- 0 (success — the Python side is set up). User can re-run install
187- later, or just run.
188- 5 . If ` ollama ` is present, probe ` http://localhost:11434/api/tags ` . If
189- the daemon is up, pull the default model (skippable via
190- ` TUTOR_SKIP_MODEL_PULL=1 ` ). If the daemon is down, print
191- ` ollama serve & ` and continue.
192- 6 . Print next-step banner: ` ./run.sh ` .
218+ 3 . ` pip install -r backend/requirements-dev.txt ` (idempotent;
219+ not gated by a prompt — those changes live inside the repo).
220+ 4 . Check ` ollama ` on ` PATH ` . If missing, ** prompt** to install via the
221+ OS-appropriate upstream installer (` brew install ollama ` on macOS,
222+ ` curl https://ollama.com/install.sh | sh ` on Linux). Decline and
223+ the script prints the manual command and continues.
224+ 5 . If ` ollama ` is present, probe ` http://localhost:11434/api/tags ` .
225+ If the daemon is down, ** prompt** to start ` ollama serve ` in the
226+ background (` nohup ` , logged to ` /tmp/ollama-serve.log ` ).
227+ 6 . If the daemon is up, check for the model
228+ (` TUTOR_MODEL ` , default ` gemma3:4b ` ). If absent, ** prompt** to
229+ ` ollama pull ` it.
230+ 7 . After setup, ** prompt** "Launch the tutor now (./run.sh)?".
231+ ` PYTHON_TUTOR_AUTOLAUNCH=1 ` or ` PYTHON_TUTOR_ASSUME_YES=1 ` answers
232+ yes without asking.
193233
194234### ` run.sh `
195235
196- 1 . Ensure venv exists (re-run ` install.sh ` if not).
197- 2 . Probe Ollama; warn if unreachable but continue.
236+ 1 . Ensure venv exists (re-run ` install.sh ` in non-interactive,
237+ skip-Ollama mode if not — this never installs system binaries).
238+ 2 . Probe Ollama; if installed but the daemon is down, ** prompt** to
239+ start ` ollama serve ` . If declined, warn and continue.
1982403 . Launch uvicorn with ` TUTOR_SERVE_FRONTEND=1 ` so the backend serves
199241 the static frontend on the same port.
2002424 . Print the URL: ` http://localhost:8001/ ` .
@@ -206,25 +248,34 @@ This blend has:
206248- ` TUTOR_MODEL ` — Ollama model tag (default ` gemma3:4b ` ).
207249- ` TUTOR_SKIP_OLLAMA=1 ` — skip every Ollama probe (CI/offline-dev).
208250- ` TUTOR_SKIP_MODEL_PULL=1 ` — skip ` ollama pull ` in install.
209- - ` TUTOR_NONINTERACTIVE=1 ` — never prompt; assume defaults.
251+ - ` TUTOR_NONINTERACTIVE=1 ` — never prompt; auto-answer ** no** .
252+ - ` PYTHON_TUTOR_NONINTERACTIVE=1 ` — alias for the above.
253+ - ` PYTHON_TUTOR_ASSUME_YES=1 ` — never prompt; auto-answer ** yes** .
254+ - ` PYTHON_TUTOR_AUTOLAUNCH=1 ` — ` exec ./run.sh ` after install
255+ without asking.
210256
211257## What the user does
212258
259+ Default interactive flow:
260+
213261``` bash
214262gh repo clone StewAlexander-com/python-tutor
215263cd python-tutor
216- ./install.sh # ~2 min cold; reuses cache on re-run
217- ./run.sh # opens at http://localhost:8001/
264+ ./install.sh # ~2 min cold; prompts y/N for each system action
265+ # answer 'y' to install Ollama, start the daemon,
266+ # pull the model, and launch the app
218267```
219268
220- If Ollama is missing, ` install.sh ` will tell them exactly what to type:
269+ If you'd rather drive it yourself, decline every prompt and the script
270+ still finishes successfully — only the Python side is set up, with
271+ clear hints for what to run next.
272+
273+ Unattended:
221274
222275``` bash
223- # macOS
224- brew install ollama && ollama serve &
276+ # Pre-approved: install Ollama, start it, pull the model, exec run.sh.
277+ PYTHON_TUTOR_ASSUME_YES=1 ./ install.sh
225278
226- # Linux
227- curl -fsSL https://ollama.com /install.sh | sh && ollama serve &
279+ # CI: do not touch Ollama at all.
280+ TUTOR_SKIP_OLLAMA=1 TUTOR_NONINTERACTIVE=1 . /install.sh
228281```
229-
230- Then ` ./install.sh && ./run.sh ` again.
0 commit comments