> ## Documentation Index
> Fetch the complete documentation index at: https://docs.staging.questra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Live updates

> What each Program workflow publishes for live subscribe — NDJSON World streams, UIMessage SSE, reconnect, and tip reconciliation.

This page is the catalog of **in-flight** channels. Pair every live subscribe with tip reconciliation (webhooks + REST) when you reconnect, miss chunks, or are not attached to a run.

## Shared rules

1. **Subscribe with a run id** from the domain start response (`workflow_id`, or `x-workflow-run-id` for chat).
2. **Retries stay on the same run** — more chunks on the same stream.
3. **A new start is a new run** — newest-wins cancels the prior run; switch streams.
4. **Reconnect** with `startIndex` (NDJSON) while the World retains the run.
5. **Tip reconcile** with webhooks + REST — never a second survey-wide pub/sub bus.

Live NDJSON for new UIs is the **generic** World stream:

```http theme={null}
GET /v1/workflows/{workflowId}/stream?startIndex=
```

| Channel                                         | Protocol             | Endpoint                                          |
| ----------------------------------------------- | -------------------- | ------------------------------------------------- |
| Programming / clarifications / audit / populate | NDJSON               | `GET /v1/workflows/{workflowId}/stream`           |
| Programming (legacy domain)                     | NDJSON               | `GET .../programming/stream`                      |
| Clarifications (legacy domain)                  | NDJSON               | `GET .../runs/{runId}/stream` where still exposed |
| Content-edit chat                               | AI SDK UIMessage SSE | `POST .../conversations/.../messages`             |
| Tip / lifecycle fanout                          | Webhooks + REST      | Account webhooks; `GET` tip resources             |

* Content-Type: `application/x-ndjson`
* Omit `startIndex` or pass `0` to read from the start
* Positive index = resume; negative = tail-relative when the World supports it
* There is no Program archive after World data ages out — reconnect while the run’s stream is retained

Domain start responses set `stream_url` to the generic path.

***

## `survey.questionnaire_clarifications`

|               |                                                                                                                                                 |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Start**     | `POST /v1/surveys/{surveyId}/questionnaire/clarifications` → **202**                                                                            |
| **Live**      | `stream_url` → NDJSON World / anatomy chunks                                                                                                    |
| **Reconcile** | `GET .../questionnaire/clarifications`; thin `GET .../clarifications/runs/{runId}` when present; webhook `questionnaire.clarifications.updated` |

Answers/skips are **not** streamed — use tip `PATCH` and optional webhook/GET. Details: [Questionnaire clarifications](/workflows/questionnaire-clarifications).

***

## `survey.audit`

|               |                                                                                                                    |
| ------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Start**     | `POST /v1/surveys/{surveyId}/audits` → **202** `{ data: audit }` (body: `{ content_revision?, focus? }`)           |
| **Live**      | `GET /v1/workflows/{audit.workflow_id}/stream` (anatomy + `audit.issue` chunks)                                    |
| **Reconcile** | `GET /v1/workflows/{workflowId}`; `GET /v1/surveys/{surveyId}/audits/{auditId}` and `.../findings`                 |
| **UI**        | Review chat tool `audit_against_questionnaire` streams a live checklist, then completes with persisted finding ids |

Detection compares tip questionnaire prose + answered clarifications to the **pinned content revision** snapshot. Nested body chunks are `{ type: "audit.issue", issue }` between `step.started` and `step.ended`. Domain responses do not include `stream_url`.

## `survey.audit.remediate`

|               |                                                                                               |
| ------------- | --------------------------------------------------------------------------------------------- |
| **Start**     | `POST /v1/surveys/{surveyId}/audits/{auditId}/remediations` → **202** `{ data: remediation }` |
| **Live**      | `GET /v1/workflows/{remediation.workflow_id}/stream`                                          |
| **Reconcile** | `GET /v1/workflows/{workflowId}`; `GET .../remediations/{remediationId}`                      |

Mutates the audit **proposed source** only — never the content tip. The Review agent does not start this workflow; it patches the dirty Monaco buffer and PATCHes findings.

***

## `survey.programming`

|               |                                                                                                                       |
| ------------- | --------------------------------------------------------------------------------------------------------------------- |
| **Start**     | `POST /v1/surveys/{surveyId}/programming` → **202**                                                                   |
| **Live**      | `stream_url` → `GET /v1/workflows/{workflow_id}/stream`                                                               |
| **Reconcile** | `GET /v1/workflows/{workflow_id}`; `GET .../programming`; `GET .../content`; webhooks `workflow.*`, `content.updated` |

Configure gates resume via `PUT .../programming/target`, `PUT .../programming/template`, or `POST /v1/workflows/{id}/hooks/{token}` when following anatomy `resumePath`. After Push, PFQ emits a hidden `{ asyncContinuation: true }` and a single **Audit** step (`contentFormat: todo`) that starts `survey.audit` / `survey.audit.remediate` as children; Continue to Review is allowed while Audit still runs. See [Programming](/workflows/programming).

***

## `survey.content_edit`

|               |                                                                                  |
| ------------- | -------------------------------------------------------------------------------- |
| **Start**     | `POST .../conversations/{conversationId}/messages` → **200** SSE                 |
| **Live**      | AI SDK UIMessage SSE on the POST response                                        |
| **Reconcile** | `GET .../messages` (persisted UIMessages); webhook `content.updated` on finalize |

This path uses the World **default** model-call stream (`ModelCallStreamPart`), transformed to UIMessage SSE — **not** an NDJSON programming/clarifications/audit stream.

Details: [Content edit](/workflows/content-edit).

***

## What is *not* a live workflow stream

| Mechanism                                                 | Role                                            |
| --------------------------------------------------------- | ----------------------------------------------- |
| Account webhooks                                          | At-least-once tip/lifecycle fanout for backends |
| Tip REST (`GET .../content`, `GET .../clarifications`, …) | Source of truth after the fact                  |

Prefer run streams (or conversation SSE) while attached to a run; prefer webhooks + REST when you are not.
