--- id: "b979a745-83ab-4377-ade1-56893004c2f6" name: "ChatGPT Conversation-API Poll Contract" micro_summary: "Send→poll→extract: capture the id from the pathname at send, poll that id, and accept done only when the message count holds steady and the newest non-empty assistant message is finished. A length threshold alone fires on intermediates." status: "in_progress" see_also: [{"target": "2fd2f809-00c3-4534-9e38-2add0fe89aff", "reason": "Poll Contract's done-condition is the precondition for clean-transcript extraction; extraction genuinely depends on the poll firing first."}] scope: "Canonical send→poll→extract contract for ChatGPT dispatch: id capture at send, id-scoped polling, done-condition definition." --- ## Canonical send→poll→extract contract (2026-09-03) Send via composer → capture the conversation ID from `location.pathname` **immediately** after send (`/c/` form) → poll **that** conversation via `GET /backend-api/conversation/` → done condition: a **new** assistant message appearing **after** our user message, with `status === 'finished_successfully'` and real text length. ## The slug/status trap (observed failure) Matching "latest conversation" by slug (`slug.indexOf('rlm') >= 0` etc.) grabbed the wrong conversation. Status-only or blank polls are unreliable failure signals. ## Warnings - Never slug-match "latest conversation" — poll the id captured at send time. - Never trust a blank/status-only poll as failure; verify with the id-captured poll before concluding anything. - Extract via the ChatGPT Clean Transcript recipe only after the done condition fires. --- ### 2026-09-17 19:13 UTC ### 2026-09-17 UTC The stated done condition produced a false positive. Treating "newest assistant message is `finished_successfully` and longer than some threshold" as complete fired on a 599 character intermediate message while a 20683 character answer was still being produced. Long reasoning turns also insert empty `finished_successfully` assistant entries into the lineage, so a bare count of assistant messages is not progress either. Working condition: poll the captured id, and accept completion only when the message count stops changing between consecutive polls and the newest non-empty assistant message is finished and plausible as a final answer. Extract with the plain transcript recipe only after that holds.