Jira Key
DM-55470
Jira URL
https://rubinobs.atlassian.net/browse/DM-55470
Summary
Times Square now reports terminal notebook-execution failures as an additive execution_error object (code, title, message) on both GET /v1/pages/{page}/htmlstatus and the html/events SSE stream (lsst-sqre/times-square#165–#168), instead of returning HTTP 500 on every poll. Squareone cannot yet reach that terminal state: the non-strict zod schemas silently strip the new field, useHtmlStatus polls unconditionally at 1 s, and both SSE consumers' auto-close condition (execution_status === 'complete' && html_hash) can never fire on a failure — so a user viewing a failing notebook still sees an infinite "Loading...". This PRD adopts the new contract: surface the failure, stop polling/streaming, and offer a Re-run action.
Server-side behavior the UI can rely on: execution_error is terminal (stop polling when non-null); available stays false in the failure case; a failure becomes retryable server-side after a TTL (default 600 s); an explicit re-run via DELETE /v1/pages/{page}/html?{params} clears the cached failure immediately; and while stale cached HTML exists (background refresh), neither API ever reports execution_error — the UI never needs an "error while content is showing" state.
Scope
In scope — packages/times-square-client:
- Add an
ExecutionErrorSchema (title, message strings; code parsed as z.string() for forward compatibility, with the known values timeout, jupyter_error, unknown, result_unavailable documented and exported as a const) and add execution_error to HtmlStatusSchema and HtmlEventSchema as optional-nullable defaulting to null, so the client keeps working against pre-DM-55470 Times Square deployments.
useHtmlStatus: expose executionError in the return shape and treat non-null as terminal — refetchInterval becomes a function that stops polling when the latest data carries an execution_error. All other polling behavior (1 s cadence, refetch-on-focus, behavior when available) is unchanged.
sse.ts / subscribeToHtmlEvents: extend the auto-abort condition so a non-null execution_error also completes the subscription (invoking onComplete and closing the stream); the terminal event is still delivered to onEvent first.
- New client function + react-query mutation for
DELETE /v1/pages/{page}/html?{params} (Times Square soft delete, which requests a fresh execution and clears the cached failure). On success, invalidate the page's htmlstatus query so polling resumes automatically (the fresh response has execution_error: null).
- Update
mock-data.ts and package tests (schema parse with the field present / null / absent; terminal polling stop; SSE abort-on-failure; the mutation and its invalidation).
In scope — apps/squareone:
- Migrate
TimesSquareHtmlEventsProviderClient onto the package's subscribeToHtmlEvents, deleting its inline HtmlEvent type and duplicated fetch-event-source/abort logic; extend TimesSquareHtmlEventsContext with the execution-error fields.
TimesSquareNotebookViewerClient (and the GitHub page panel path that renders the same viewer): when the terminal failure is reached, replace the loading state with an error panel built from existing squared/design-system components showing the API's title and message (the code informs iconography/tone only — no Squareone-authored per-code copy), plus a Re-run button wired to the soft-delete mutation. After re-run, the viewer returns to its loading state and resumes polling.
- Update the dev mock API routes (
apps/squareone/src/app/api/dev/times-square/.../htmlstatus/route.dev.ts and friends) with failure-state examples so the flow is exercisable in dev mode.
- Re-vendor
packages/times-square-client/openapi.json from a Times Square release that includes DM-55470 (the periodic openapi-drift CI will otherwise go red on its own, as it did before squareone#618).
- Changesets for the package and app per repo convention.
Out of scope:
- Any Times Square server change (all four DM-55470 PRs land independently in lsst-sqre/times-square).
- Per-code guidance copy authored in Squareone beyond the API's
title/message.
- Changing polling cadence or stopping polling in the success/
available case.
- The known PR-preview page-data 404 issue in
useTimesSquarePage (separate bug, tracked independently).
Acceptance criteria
Open questions
None — ready to break into tasks.
Jira Key
DM-55470
Jira URL
https://rubinobs.atlassian.net/browse/DM-55470
Summary
Times Square now reports terminal notebook-execution failures as an additive
execution_errorobject (code,title,message) on bothGET /v1/pages/{page}/htmlstatusand thehtml/eventsSSE stream (lsst-sqre/times-square#165–#168), instead of returning HTTP 500 on every poll. Squareone cannot yet reach that terminal state: the non-strict zod schemas silently strip the new field,useHtmlStatuspolls unconditionally at 1 s, and both SSE consumers' auto-close condition (execution_status === 'complete' && html_hash) can never fire on a failure — so a user viewing a failing notebook still sees an infinite "Loading...". This PRD adopts the new contract: surface the failure, stop polling/streaming, and offer a Re-run action.Server-side behavior the UI can rely on:
execution_erroris terminal (stop polling when non-null);availablestaysfalsein the failure case; a failure becomes retryable server-side after a TTL (default 600 s); an explicit re-run viaDELETE /v1/pages/{page}/html?{params}clears the cached failure immediately; and while stale cached HTML exists (background refresh), neither API ever reportsexecution_error— the UI never needs an "error while content is showing" state.Scope
In scope —
packages/times-square-client:ExecutionErrorSchema(title,messagestrings;codeparsed asz.string()for forward compatibility, with the known valuestimeout,jupyter_error,unknown,result_unavailabledocumented and exported as a const) and addexecution_errortoHtmlStatusSchemaandHtmlEventSchemaas optional-nullable defaulting tonull, so the client keeps working against pre-DM-55470 Times Square deployments.useHtmlStatus: exposeexecutionErrorin the return shape and treat non-null as terminal —refetchIntervalbecomes a function that stops polling when the latest data carries anexecution_error. All other polling behavior (1 s cadence, refetch-on-focus, behavior whenavailable) is unchanged.sse.ts/subscribeToHtmlEvents: extend the auto-abort condition so a non-nullexecution_erroralso completes the subscription (invokingonCompleteand closing the stream); the terminal event is still delivered toonEventfirst.DELETE /v1/pages/{page}/html?{params}(Times Square soft delete, which requests a fresh execution and clears the cached failure). On success, invalidate the page's htmlstatus query so polling resumes automatically (the fresh response hasexecution_error: null).mock-data.tsand package tests (schema parse with the field present / null / absent; terminal polling stop; SSE abort-on-failure; the mutation and its invalidation).In scope —
apps/squareone:TimesSquareHtmlEventsProviderClientonto the package'ssubscribeToHtmlEvents, deleting its inlineHtmlEventtype and duplicated fetch-event-source/abort logic; extendTimesSquareHtmlEventsContextwith the execution-error fields.TimesSquareNotebookViewerClient(and the GitHub page panel path that renders the same viewer): when the terminal failure is reached, replace the loading state with an error panel built from existing squared/design-system components showing the API'stitleandmessage(thecodeinforms iconography/tone only — no Squareone-authored per-code copy), plus a Re-run button wired to the soft-delete mutation. After re-run, the viewer returns to its loading state and resumes polling.apps/squareone/src/app/api/dev/times-square/.../htmlstatus/route.dev.tsand friends) with failure-state examples so the flow is exercisable in dev mode.packages/times-square-client/openapi.jsonfrom a Times Square release that includes DM-55470 (the periodic openapi-drift CI will otherwise go red on its own, as it did before squareone#618).Out of scope:
title/message.availablecase.useTimesSquarePage(separate bug, tracked independently).Acceptance criteria
htmlstatusresponse carryingexecution_error, the notebook viewer stops issuing further status requests and renders the error panel with the API's title and message.execution_error, the subscription closes (onComplete fires, stream aborted) and the same terminal UI state is reached.DELETE /v1/pages/{page}/htmlwith the page instance's parameters; the viewer returns to the loading state, polling resumes, and a subsequent successful render displays HTML.execution_errorkey), all schemas parse and the UI behaves exactly as today.TimesSquareHtmlEventsProviderClientcontains no SSE transport code of its own — it consumessubscribeToHtmlEvents.packages/times-square-client/openapi.jsonis re-vendored and the openapi-drift CI check is green.Open questions
None — ready to break into tasks.