@codexstar/pi-listen 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,227 @@
1
+ # pi-voice review findings
2
+
3
+ ## Scope reviewed
4
+
5
+ Reviewed the current implementation changes around:
6
+ - config migration and persistence
7
+ - diagnostics and recommendation logic
8
+ - onboarding flow wiring
9
+ - provisioning-plan helpers
10
+ - package/docs updates
11
+
12
+ I also sanity-checked that the repo still passes its current verification command (`bun run check`).
13
+
14
+ ## Summary
15
+
16
+ The recent changes are a strong step forward: config handling is now modular, there is automated coverage for config/diagnostics/provisioning logic, first-run onboarding is wired, and docs/package metadata exist.
17
+
18
+ However, there are still a few meaningful correctness and product-integration gaps that should be fixed before calling the onboarding flow production-grade.
19
+
20
+ ---
21
+
22
+ ## Findings
23
+
24
+ ### 1. Partial legacy configs are migrated as "fully onboarded" even when they are incomplete
25
+ **Severity:** high
26
+
27
+ **Where:**
28
+ - `extensions/voice/config.ts:109-122`
29
+ - `extensions/voice/config.ts:183-186`
30
+
31
+ **What happens:**
32
+ `migrateConfig()` sets `fallbackCompleted = hasExplicitLegacyData`, and `hasExplicitLegacyData` is true for any non-empty `voice` object. That means a legacy config like:
33
+
34
+ ```json
35
+ {
36
+ "voice": {
37
+ "enabled": true
38
+ }
39
+ }
40
+ ```
41
+
42
+ will be treated as onboarding-complete after migration, even though it has no explicit backend choice, no scope choice, and no validated setup state.
43
+
44
+ Because `needsOnboarding()` only checks `source === "default"` or `!config.onboarding.completed`, these partially configured users will skip first-run onboarding entirely.
45
+
46
+ **Why it matters:**
47
+ This can strand existing users in a half-configured state while the new first-run setup never appears.
48
+
49
+ **Recommended fix:**
50
+ Only mark migrated configs as onboarding-complete when the legacy data contains enough meaningful setup information, for example:
51
+ - explicit backend + model, or
52
+ - an explicit onboarding block, or
53
+ - a post-migration validation pass succeeds.
54
+
55
+ At minimum, replace the current `Object.keys(rawVoice).length > 0` heuristic with a validity check.
56
+
57
+ ---
58
+
59
+ ### 2. Local onboarding silently dead-ends when backend scan returns no local entries
60
+ **Severity:** high
61
+
62
+ **Where:**
63
+ - `extensions/voice/onboarding.ts:70-72`
64
+ - `extensions/voice/onboarding.ts:162-167`
65
+
66
+ **What happens:**
67
+ For the local path, `runVoiceOnboarding()` filters `diagnostics.backends` down to local backends and passes the result to `chooseBackendAndModel()`. If the backend scan failed, Python is missing, or the list is empty for any reason, `chooseBackendAndModel()` returns `undefined` immediately.
68
+
69
+ That bubbles up as a cancelled setup, and the caller shows:
70
+ - `Voice setup skipped. Run /voice setup anytime.`
71
+
72
+ **Why it matters:**
73
+ This is exactly the scenario where onboarding should be most helpful. Instead, users who need guided local installation get bounced out of setup without a backend choice or a concrete recovery screen.
74
+
75
+ **Recommended fix:**
76
+ When no local backends are discoverable, synthesize fallback onboarding options instead of aborting. For example:
77
+ - show `faster-whisper`, `moonshine`, `whisper-cpp`, `parakeet` as installable options
78
+ - keep the install/provisioning hints visible
79
+ - only block if the user explicitly cancels
80
+
81
+ In other words: discovery failure should still lead to a guided install path, not a silent exit.
82
+
83
+ ---
84
+
85
+ ### 3. Onboarding is marked complete before provisioning or validation succeeds
86
+ **Severity:** high
87
+
88
+ **Where:**
89
+ - `extensions/voice/onboarding.ts:123-135`
90
+ - `extensions/voice.ts:666-677`
91
+ - `extensions/voice.ts:867-882`
92
+
93
+ **What happens:**
94
+ `runVoiceOnboarding()` returns a config with:
95
+ - `onboarding.completed = true`
96
+ - `completedAt = now`
97
+
98
+ This happens before any provisioning, daemon warmup, or transcription validation succeeds.
99
+
100
+ Then `voice.ts` saves the config and immediately shows `Voice setup complete.`. If `ensureDaemon(config)` fails, the success receipt has already been emitted.
101
+
102
+ **Why it matters:**
103
+ Users can end up with:
104
+ - onboarding marked complete
105
+ - startup onboarding suppressed in future sessions
106
+ - a broken local/cloud setup that never actually worked
107
+
108
+ This is the biggest remaining integration gap between onboarding, provisioning, and validation.
109
+
110
+ **Recommended fix:**
111
+ Split onboarding state into at least two phases, for example:
112
+ - `selected` / `configured`
113
+ - `validated`
114
+
115
+ Only mark `onboarding.completed = true` after:
116
+ - required provisioning checks pass, and
117
+ - daemon startup / provider validation succeeds, and ideally
118
+ - a real mic/transcription smoke test passes.
119
+
120
+ If validation fails, persist a repair-needed state instead of a completed state.
121
+
122
+ ---
123
+
124
+ ### 4. `/voice doctor` suggests fixes for the recommendation, not for the user’s current config
125
+ **Severity:** medium
126
+
127
+ **Where:**
128
+ - `extensions/voice.ts:900-931`
129
+
130
+ **What happens:**
131
+ `/voice doctor` computes a recommendation, then builds the provisioning plan from that recommendation:
132
+
133
+ - `mode: recommendation.mode`
134
+ - `backend: recommendation.backend`
135
+ - `model: recommendation.model`
136
+
137
+ That means the suggested commands can describe how to install the recommended path rather than how to repair the user’s actual current setup.
138
+
139
+ Example failure mode:
140
+ - user has selected `whisper-cpp`
141
+ - doctor recommends `faster-whisper`
142
+ - doctor outputs `python3 -m pip install faster-whisper`
143
+ - but the actual thing the user needs may be `brew install whisper-cpp` or model-file remediation
144
+
145
+ **Why it matters:**
146
+ Doctor output should first help the user fix the configuration they are using now. Recommendations are useful, but they should be presented separately.
147
+
148
+ **Recommended fix:**
149
+ Show two sections:
150
+ 1. **Repair current setup** — based on the current saved config
151
+ 2. **Recommended alternative** — based on the recommendation engine
152
+
153
+ Do not conflate them into one provisioning plan.
154
+
155
+ ---
156
+
157
+ ### 5. README configuration example is now stale relative to the code
158
+ **Severity:** low
159
+
160
+ **Where:**
161
+ - `README.md:152-160`
162
+
163
+ **What happens:**
164
+ The README still shows the old minimal config shape:
165
+ - `enabled`
166
+ - `language`
167
+ - `backend`
168
+ - `model`
169
+
170
+ But the implementation now uses a richer versioned shape with:
171
+ - `version`
172
+ - `mode`
173
+ - `scope`
174
+ - `onboarding`
175
+ - `btwEnabled`
176
+
177
+ **Why it matters:**
178
+ The new docs correctly talk about scope-aware onboarding and versioned config, so the example block is now misleading and under-documents the actual stored state.
179
+
180
+ **Recommended fix:**
181
+ Update the example to either:
182
+ - show the current real shape, or
183
+ - explicitly label the short example as “minimal conceptual example” and add a second “actual saved shape” example.
184
+
185
+ ---
186
+
187
+ ### 6. "Remind me later" is not persisted, so the prompt will repeat every fresh session
188
+ **Severity:** low
189
+
190
+ **Where:**
191
+ - `extensions/voice/onboarding.ts:20-27`
192
+ - `extensions/voice.ts:661-682`
193
+
194
+ **What happens:**
195
+ When the user chooses `Remind me later`, no state is written. The extension simply notifies and returns.
196
+
197
+ Because `needsOnboarding()` will still be true on the next session, the same prompt will appear again.
198
+
199
+ **Why it matters:**
200
+ This is not a runtime correctness bug, but it is a noticeable polish gap for a “world-class” onboarding experience.
201
+
202
+ **Recommended fix:**
203
+ Persist a lightweight defer marker such as:
204
+ - `onboarding.skippedAt`
205
+ - `onboarding.deferUntil`
206
+
207
+ Then suppress the startup prompt until the defer window expires or the user explicitly runs `/voice setup`.
208
+
209
+ ---
210
+
211
+ ## What looks good
212
+
213
+ These changes are solid and worth keeping:
214
+ - modular config extraction in `extensions/voice/config.ts`
215
+ - deterministic tests for config, diagnostics, and provisioning helper logic
216
+ - config-scoped socket derivation via `getSocketPath()`
217
+ - explicit backend/model on daemon transcription requests
218
+ - first-run onboarding hook on interactive `session_start`
219
+ - package scripts + docs now exist
220
+
221
+ ## Recommended priority order for fixes
222
+
223
+ 1. **Fix migrated partial configs being treated as completed**
224
+ 2. **Fix onboarding completion semantics so success requires validation**
225
+ 3. **Fix local onboarding dead-end when discovery returns zero local backends**
226
+ 4. **Split `/voice doctor` into current-config repair vs recommended alternative**
227
+ 5. **Persist “remind me later” and refresh README config example**