diff --git a/scratch/design-convey-error-wave0.md b/scratch/design-convey-error-wave0.md deleted file mode 100644 index 48b78367d..000000000 --- a/scratch/design-convey-error-wave0.md +++ /dev/null @@ -1,172 +0,0 @@ -# Design: convey-error-handling Wave 0 - -This file is the lode-local decision log target for Wave 0. The final decision table will also be mirrored into the spec at commit time. - -## Decision log - -| # | Decision | Chosen | Rationale | -|---|----------|--------|-----------| -| 1 | `api.js` housing | Add `convey/static/api.js`; insert it in `convey/templates/app.html` immediately after `websocket.js` and before the inline sidebar-state script. | That load point runs after `window.appEvents` exists and before any workspace/background consumers, while staying clear of `SurfaceState` and `AppServices` init ordering. | -| 2 | `saveControl` housing | Keep `saveControl` in `convey/static/api.js` beside `ApiError` and `apiJson`. | The save helper depends on the fetch/error contract, so keeping them together avoids split ownership and duplicate imports. | -| 3 | `appEvents.listen` overload | Keep the existing two-arg form and add `(tract, options, fn)` auto-detected by `typeof options === 'object' && typeof fn === 'function'`; the overloaded return stays the cleanup function and is augmented with `pending.track(corrId)` / `pending.clear(corrId)`. | Preserving the cleanup-function return keeps all existing listeners compatible. Attaching `pending` to the returned cleanup function avoids adding a second public API just for correlation tracking. | -| 4 | `onParseError` routing | Add `appEvents.onParseError(fn)`; on websocket parse failure, keep the existing `console.warn`, call every registered parse-error handler, and call `window.logError(error, { context: 'websocket-parse' })` if defined. | This keeps current console visibility, adds explicit subscriber hooks, and routes parse failures into the existing owner-visible error log when available. It also means `error-handler.js` must expose `window.logError`. | -| 5 | `replaceLoading` heuristic | Add `SurfaceState.replaceLoading(container, options)` with the exact heuristic from the scope: if `container.querySelector('.surface-state--loading')` is truthy, treat it as first paint and `replaceChildren(...)`; otherwise manage a singleton `.surface-state-refresh-error` sibling after the last non-error child. | The heuristic matches the audited failure split between first-paint emptiness and refresh-on-stale-content without forcing every caller to hand-roll placement rules. | -| 6 | `registerTask` 403 behavior | On `ApiError.status === 403`, stop the interval, set `health.disabled = true`, do not tint the menu pip, do not notify, and retain the task record in `AppServices.getTaskHealth(appName)`. `registerTask` owns the no-auth-redirect behavior internally so consumers do not pass `noAuthRedirect`. | Support uses `403` as a real disabled state, not a broken-state signal. Centralizing that rule inside `registerTask` keeps background consumers simple and makes diagnostics consistent. | -| 7 | `.menu-item-bg-failing` visual | Apply the class to the existing `