Skip to content

[Bug] v6.1.13 rich user-message rendering changes staged JSON despite a matching acknowledgement #886

Closed

Description

@nofihq

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 pre block, one .rich-text-user-turn paragraph.
  • 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\\", \&lt;placeholder&gt;, \*\*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

  1. added
    P1High: major user-facing failure; address next
    LinuxSpecific to Linux
    fix: committed-unreleasedThe fix is committed but not included in a published release
    needs retestWaiting for the original scenario to be retested on a published release.
    on Oct 22, 2026
  2. miuuyy commented on Oct 22, 2026

    @miuuyy
    Owner

    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.

  3. miuuyy commented on Oct 26, 2026

    @miuuyy
    Owner

    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.

  4. added
    fix: releasedThe fix is included in a published release
    and removed
    fix: committed-unreleasedThe fix is committed but not included in a published release
    on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    LinuxSpecific to LinuxP1High: major user-facing failure; address nextfix: releasedThe fix is included in a published releaseneeds retestWaiting for the original scenario to be retested on a published release.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions