Files

6.7 KiB

Filbert review, row 154 round 1: changes

Candidate manifest ecaec3293be94ed968588eeb3332b6b7e23289dedbf935d06106a494495f04cb (195 paths), base 0f715a054. I reviewed and ran on 0f715a054 plus Researcher's candidate.patch. All 195 hashes match before and after every run. The packages/webui/src/public/ diff and the imported source still need Mos's decision 123 go on the candidate.

One change is requested, a single test. Everything else checks out, including the byte-for-byte rebuild.

1. Byte-for-byte rebuild: confirmed

In packages/webui, I ran:

  1. npm ci --ignore-scripts --no-audit --no-fund from the package-local lock. The lock sha256 is eb60a494...f63f. It installed esbuild 0.28.2, and the linux-x64 binary sha256 is e1698a3d...4100, as editor/toolchain.mjs pins.
  2. MOSAIC_REQUIRE_EDITOR_BUILD=1 node editor/toolchain.mjs, which exited 0.
  3. node editor/build.mjs --out into my scratch. editor.js is c601f6c3f75b7cf9898a9a52abfdab3e50badbcb5f66e57e6df57641878e6565, 757137 B; editor.css is 8654ac57d1e7a561110138ecd7f701c34a074017ff8c4cd2768d8083908ee61f. cmp shows editor.js, editor.css and BUILD.json identical to the shipped files.
  4. The literal node editor/build.mjs in place. All 195 manifest hashes were unchanged afterwards.

Because the build ran from my own path, this also confirms the README's claim that builds from different absolute paths give identical bytes. esbuild printed one [ignored-bare-import] warning for import "./mark" in prosemirror-transform/src/index.ts. BUILD.md:198 discloses it, and it is harmless: mark.ts only exports functions, and transform.ts imports them directly. editor-provenance.test.mjs:159 ran rather than skipped under MOSAIC_REQUIRE_EDITOR_BUILD=1 (6/6, 0 skipped).

2. Round-trip and save tests

  • editor.test.mjs:32 round-trips the goals review and EVERY exactly. :40 asserts that every .md under docs/ and spec/ round-trips, with CRLF normalised to LF as row 148 saves.
  • editor-browser.test.mjs:323 types into one paragraph and asserts the whole saved content string. Only that block is rewritten, with the typed ** escaped; the table, heading and last paragraph come back byte for byte. The body keys are row 148's {base, content, path, project}, and the second save is based on the first save's commit.
  • :246 checks that pasted image spans survive into a save only for targets the gate accepts. :154 checks that pasted links and the link bar refuse javascript:, data:, vbscript:, protocol-relative and bad-host targets.
  • Row 148's save tests in docs-browser.test.mjs pass (1/1). Their assertions are unchanged. The open helper and three waits now go through a new source() helper that clicks Source first, which the README discloses.

3. The mode switch reuseDraft fix: correct and pinned

docView(get, project, file, { reuseDraft = false } = {}) rereads only when !s || (!dirty(s) && !reuseDraft) (bus.js:690). The mode click passes { reuseDraft: true } explicitly through render, view and docView (bus.js:744); it is not a module flag that later navigation could inherit. editor-browser.test.mjs:283 counts the reads:

  • two Visual/Source round trips read nothing;
  • Reload reads once;
  • a switch after Reload reads nothing;
  • going away and back reads once.

My m1 (drop && !reuseDraft) and m2 (click without { reuseDraft: true }) are both killed by :283 and :323.

4. The browser.test.mjs script-list pin

browser.test.mjs:22 deep-equals the page's script src list against ['/editor.js', '/brand.js', '/app.js', '/markdown-preview.js', '/bus.js'], which is order and count, not a bare count. My m4 (moving editor.js after brand.js in index.html) is killed by it. serve.mjs changes only by the two static entries (serve.mjs:26-27), and serve.test.mjs:36 serves both.

Row 129 overlap

BUILD.md's "Row 129 overlap" section matches what I expect: browser.test.mjs:22, index.html and the serve.test.mjs path list conflict textually, not semantically. Row 129 landed first, so the r2 rebase must pin all six scripts in page order and keep row 129's named /chat.js check. I'll review that delta when it comes.

Change requested

Test the Source fallback when the round trip fails. The visual editor opens only if window.MosaicEditor.roundTrip(s.text) === s.text (bus.js:703). Otherwise the file opens in Source with the note "The visual editor is not available for this file, so it is open as source." (bus.js:704). This gate is what keeps brief item 5 ("A file opened and saved with no edits saves the same bytes") true for a file nobody has tried yet. The README states the behaviour at README.md:515.

My m3 replaced the gate with visualOk = true; and survived editor-browser.test.mjs. No test opens a file that fails the round trip, because every repository doc passes it. A browser test can still reach the gate: replace window.MosaicEditor before the page opens the file, with a roundTrip that returns different text and the real mount. Then assert that #doc-text is shown, that the note is present, that no .ProseMirror exists, and that Save stays off with no edit. Covering the !window.MosaicEditor branch (editor.js failed to load) in the same test would be cheap.

Non-blocking notes

  • bus.js:743: when a file falls back to Source, docMode stays 'visual'. Clicking Visual then returns early (mode === docMode), so the button does nothing; Source still works. The behaviour is harmless, but the aria-pressed Visual button is a dead control here. The new test could pin whichever behaviour you choose.
  • docs-browser.test.mjs: the third replaced wait dropped #doc-commit textContent !== ""; source() waits only for #doc-commit to exist. The #doc-commit text assertion follows right after it, so a slow render could fail that test intermittently. It is not a weakened assertion.

Ran by me

Slot from sage-0792. The busy check was CLEAR before each step, the manifest was checked before and after, TMPDIR was in my own scratch, and DOCKER_HOST was a dead socket.

  • Rebuild: 17:16:38Z to 17:16:39Z, as in section 1.
  • Singles, 17:16:49Z to 17:17:09Z, with MOSAIC_REQUIRE_EDITOR_BUILD=1: editor 5/5, editor-provenance 6/6, editor-browser 5/5, docs-browser 1/1, browser 1/1, serve 4/4, project-file 10/10, markdown-preview 19/19. The awk sum is 51/51, 0 skipped.
  • Mutants, 17:17:14Z to 17:17:42Z. The controls for editor-browser and browser passed first. m1, m2 and m4 were killed as described above. m3 (the round-trip gate) survived.

Not mine

Researcher's slot run (BUILD.md "Results"), 16:48:49Z to 16:51:57Z: webui 162/162 with MOSAIC_REQUIRE_EDITOR_BUILD=1, and Researcher's own rebuild check at 16:52Z.