Commit Graph
4 Commits
Author SHA1 Message Date
Ludo FourrageandClaude Opus 5.5 308de1fd4d fix(voice): 30 s and Manual outlast silent Web Speech runs
_onWebSpeechEnd counted every run that ended without a result toward the
two-retry cap, however long the run lasted. Under 30 s or Manual, each
no-speech window of the engine is one silent run, so the third ended the
recording at about 18 s of silence, before the deadline, and Manual
stopped on its own. Both recognition.start() sites now stamp the run start;
an empty run counts toward the cap only when it ended within a second of
starting (a recognizer that cannot listen), and any other run resets it.
The 250 ms backoff is unchanged.

The vm harness in test/voice-silence-timeout.test.ts now passes the test's
Date into the context, whose own Date ignores fake timers.

Also from review: the VoiceInput stubs of the four settings-ui.js tests
carry SILENCE_TIMEOUT_SECONDS; Settings-Reference lists Stop after silence;
the touchscreen Linux fallback leaves out ChromeOS and says a touch Linux
laptop still matches; the dead _webSpeechStream teardown is gone; the two
voice tests use vitest expect instead of node:assert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 07:57:14 -08:00
JD a1406f1753 fix(settings): stop a failed settings write from saying it was saved
App Settings' save handled only the multi-user admin-only 403 and the tunnel's no-password 403, so a 409 for a settings.json that does not parse, a 400, a 500 or a dropped connection (`_apiPut` answers null) still toasted "Settings saved" and closed the modal, and the run mode and respawn preset writes failed with no word at all. Those failures now warn with the server's reason (else the HTTP status, else that the server could not be reached), the modal stays open, and nothing that assumes the server stored the save runs: Apply's refresh, the tunnel-starting toast and the gesture-control reload. Since the modal now invites a second Save, the plan-usage collection flip and the gesture reload are judged against the settings the failed save started from until a save lands, so the retry still sends the flip and still reloads.

A save with the tunnel switch on is read as a tunnel refusal only on a 403, so another failure no longer turns the switch off or shows the no-password message, and an accepted no-password retry now resends the whole save instead of the tunnel keys alone, which had left every other setting unsaved behind "Settings saved". Run mode and respawn presets stay saved on this device as before and now say they were not saved on the server. Stopping the tunnel from the welcome screen or the tunnel panel no longer says "Tunnel stopped" when the server refused the write, since the tunnel is then still running.
2026-10-28 01:32:47 -04:00
Codeman maintainer 5a297cd3e4 fix(multi-user): read a refused settings write as admin-only in the browser
Two gaps in how a regular user's browser handled the admin-only settings
writes:

- The role comes from GET /api/me, which answers after page load, and on
  a failed request admin-ui.js falls back to a single-user admin. A save
  made then was sent, came back 403, and still said "Settings saved",
  while the refused server-wide change stayed on the device. A 403
  FORBIDDEN on a settings write now ends that save like a known
  non-admin's: synced keys back to the server's value, the one admin-only
  notice, and the page is read-only from then on (_noteSettingsWriteRefusal).
  The display-key list moved into one method (_displaySettingKeySet), so
  that split no longer depends on GET /api/settings having loaded.
- A regular user's run mode and respawn presets were skipped for the
  server but overwritten by the server's on the next page load, while
  "Saved preset" said otherwise. They are now kept as that user's own on
  the device and put back over the server's after the settings load and
  on codeman:me (_rememberOwnSetting, _applyOwnSettings).

Admins and single-user mode are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 13:12:09 +02:00
Codeman maintainer cb928aefe2 test(multi-user): pin admin-only settings writes, server and browser
- test/routes/system-routes-settings-admin-only.test.ts (app.inject): a
  non-admin PUT /api/settings is 403 FORBIDDEN before the body is parsed, and
  nothing is written, no watcher toggled, no tunnel started, no history limit
  set; the same gate on PUT /api/execution/model-config, PUT /api/config and
  PUT /api/cases/order; admins and single-user mode write as before; GET stays
  readable.
- test/settings-admin-only-multiuser.test.ts (live server, port 0, real
  multi-user auth): settings.json is byte-identical after a non-admin's PUTs,
  and a non-admin's quick-start or Ralph loop no longer records lastUsedCase.
- test/settings-admin-only-ui.test.ts (real index.html in JSDOM): a non-admin
  App Settings save sends no PUT, keeps per-device keys, keeps synced keys at
  the server value, and toasts once only on a real synced change; the
  background writes are skipped; admins still PUT; zh-CN for both toasts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 12:16:34 +02:00