Repository navigation
[Bug] v6.1.13 rich user-message rendering changes staged JSON despite a matching acknowledgement #886
Description
Version and scope
v6.1.13's multipart serializer and strict user-message reader; Linux x64, ChatGPT Web GPT-6 High. Follow-up to the request in #868 for the actual changed text and original DOM, rather than another JSON round-trip-only proposal.
The original native failure was on 6.1.13-local.rfe3b413.20261021.2: released 6.1.13 plus the disclosed #884 environment correction and passive local diagnostics, with no change to multipart serialization or message ownership. I am not describing that binary as unmodified. I then reproduced the text mutation with harmless synthetic data in a separate ordinary authenticated Chrome tab, outside the bridge. The DOM excerpt below comes from that control's original document after expanding its message; it is not a reconstruction or a reloaded native failure page.
Reproduction
From the release source, generate a payload and its normal stage:
import { writeFileSync } from 'node:fs';
import { formatChatGptWebMultipartStage, withoutRetiredTurnHandles } from './src/adapters/chatgpt-web/prompt';
const content = ('Use "quoted text", <placeholder>, **bold**, _name_, ~~old~~, [label](https://example.com).\n\n### Heading\nC:\\tmp\\file\n').repeat(700);
const payload = withoutRetiredTurnHandles(JSON.stringify({
version: 1, part_index: 1, total_parts: 2,
records: [{ kind: 'system', system_index: 0, content }],
}));
writeFileSync('context-repro.txt', formatChatGptWebMultipartStage(payload, 'ctx_' + 'a'.repeat(32), 1, 2).text);Submit the complete stage through the plain-text composer path, first verifying exact composer readback. After its acknowledgement, expand Show more and compare the complete text using the existing readChatGptUserMessage representation, including its code-block reconstruction. Do not infer equality from a preview or the acknowledgement alone.
My controlled messages used the same stage tags/JSON fence and a shortened final inert-context reminder; they did not include any plugin, tools, private source or request token. In the stock-serialization control:
- The 86,904-character payload parsed correctly before submission.
- Complete submitted stage: 87,809 characters, exact composer equality verified before Send.
- The assistant returned the exact nonce/part/payload-digest acknowledgement.
- Expanded message: 122,060 characters, no actual
preblock, one.rich-text-user-turnparagraph. - The first changed character was at offset 715, inside the payload. The full reader comparison failed.
Exact synthetic text around that first mismatch:
expected: ..."system_index":0,"content":"Use \"quoted text\", <placeholder>, **bold**, _name_, ~~old~~, [label]...
observed: ..."system_index":0,"content":"Use \\"quoted text\\", \<placeholder>, \*\*bold\*\*, \_name\_, \~\~old\~\~, [label]...
The original control DOM also contained this excerpt (excerpt only, not a proposed selector or reconstructed fixture):
<span>{"version":1,"part_index":1,"total_parts":2,"records"</span>:[{"kind":"system","system_index":0,"content":"Use \\"quoted text\\", \<placeholder>, \*\*bold\*\*, \_name\_, \~\~old\~\~, [label]<span>(</span><a data-inline-mention-interactive="" class="ExternalMarkdownLink-WWBYg9 InlineMentionFocusRing-j8iO1a" href="https://example.com).\n\n###" rel="noopener noreferrer" target="_blank" data-state="closed" data-search-result-target="">The wrapper was an actual div[data-markdown-text-tone="user-message"].rich-text-user-turn, containing a paragraph with spans/BRs and the auto-link above. The existing outer JSON fence did not prevent this rendering path.
Native failure and candidate checks
The native failure was ChatGPT opened another user turn while the bound assistant response was detached, during the first stage acknowledgement. Its original redacted DOM checkpoint is retained. In a separate read-only load of that saved conversation, the stored edit source was 246,572 characters, its 245,486-character payload was valid JSON with the declared SHA-256, and the saved acknowledgement matched. The expanded rendered version was 265,934 characters and its displayed payload was invalid JSON with a different digest. The edit inspection was canceled without submitting an edit. That secondary inspection is corroborating evidence, not the original event DOM.
I tested a multipart-only JSON-string Unicode encoding candidate while leaving full text/identity/token checks strict. Encoding delimiters without URL colons still failed in a live control; encoding only colons/backticks also failed. The revised candidate encodes the observed quote/backslash/Markdown delimiters plus URL colons in JSON string lexemes. It leaves numbers and structural JSON punctuation intact and preserves all decoded records. Record weights and emitted payloads use the same encoding; ordinary inline transport is unchanged.
For the revised synthetic control, the existing strict reader reconstructed all 158,524 submitted characters exactly, including the genuine pre[data-markdown-copy="code-block"] representation, and the acknowledgement matched. On the installed local candidate, all three native research chats then completed their stage acknowledgements (7.4–8.0 seconds) and executed real native tools. No ownership matching, broker validation, timeout, completion rule, model or effort was relaxed.
The isolated two-file candidate on release commit 6f43747 passes full verification: 1,026 core tests, 422 launcher tests, audits, typechecks and relocatable runtime smoke. The local integrated build also passed its full checks and packaged Linux smoke. These are scoped staging results. The separate empty-final failure in #885 still occurred afterward, so this is not a claim that continuous goals are fully reliable. I have not opened a PR claiming that broader outcome.
No private conversation URL, account data, real broker/control token, research contents, raw network payload or hidden reasoning is included here. The synthetic transaction ID and example URL above are test data. The original full synthetic control and content-free native checkpoints remain available for a narrower follow-up if useful.
Activity
miuuyy commentedon Oct 22, 2026
Thanks for the reproduction and the encoding experiment. I've added a fix that protects staged JSON from rich-text changes without weakening the exact submission check. It passed the regression tests and a live Plus upload; your account's rich-renderer case still needs a retest after the next patch. This is not included in v6.1.13.
fix: preserve multipart context through rich message rendering
miuuyy commentedon Oct 26, 2026
This should be addressed in v6.1.14: rich rendering of the submitted JSON no longer causes the multipart verification failure. Please update and retry. If it still fails, open a new issue with a fresh Activity → Export safe log.