Skip to content

feat(marketplace): port official 0.78.1 plugin detail page recipes - #27

Merged
tyonger-stack merged 4 commits into
mainfrom
feat/marketplace-detail-view-0781
Nov 2, 2026
Merged

tyonger-stack merged 4 commits into
mainfrom
feat/marketplace-detail-view-0781

Conversation

@tyonger-stack

@tyonger-stack tyonger-stack commented Nov 1, 2026 •

Copy link
Copy Markdown
Owner

Why

Official 0.78.1's plugin detail page renders with different recipes than upstream 0.18's, and this build shows the upstream ones. The wave before this one ported the page's structure. This wave ports the recipes on the section heading, the cards, the rows and the buttons, and it fixes a CSS injector that silently dropped two of official's rules.

What changed

  • Rewrites upstream's detail components to official's own recipes for the section heading, the card, the details row, the row label, the account title, the tools summary, the chevron and the small secondary button.
  • Reads every string the port shows from official's own locale tables, recorded in tests/fixtures/official-0781-detail-view-messages.json.
  • Fixes the CSS injector, which used a substring search to decide a rule was present. A scoped rule from this repository's computer-card patch contains the unscoped rule as a substring, so official's sand-1lun4ml and sand-pilrb4 never shipped. The injector now compares whole lines and fails closed when an official rule is missing as a standalone rule.

Scope

This covers the detail page's recipes and its own strings. It leaves the shared typography classes alone, because official's differ from upstream's across the whole app.

Tradeoffs

The Setup section stays, even though official renders nothing for these ten plugins. Official reads it from a plugin's declared fields, and this build's Setup section carries the Google and Slack OAuth client id and secret, which is the only way to configure them.

Blast Radius

The patch rewrites view-B5Ug8wEm.js at build time and adds six rules to the renderer stylesheet. The six rules belong to official's small secondary button, so the Setup section's 编辑值 button gains a 1 px border.

Verification

  • npm run check gives 2735 tests: 2698 pass, 0 fail and 37 skipped in a clean checkout, and 2701 pass, 0 fail and 34 skipped with the packaging staging directory present.
  • All 102 shipped chunks parse and the known i18n quote bug is absent. The 6 official-only rules are byte for byte official and standalone, and all 37 class tokens the ported recipes use resolve in the deployed stylesheet.
  • Measured over CDP against official 0.78.1 on port 9333, the section-aligned pixel diff is 1.055 percent for Gmail, 1.772 percent for Google Calendar and 1.905 percent for Google Drive. Official's connect button and this build's 编辑值 button carry the same class recipe and the same 1 px border.
  • The deployed build was driven with real mouse events through 连接应用, 已连接 8 个 and a plugin row.

Rebuilt on the merged manage wave

The manage wave landed first, so this branch is rebased onto it. The rebase moved two files: the port document, and a comment in scripts/clean-build.mjs.

The packaged app.asar is not bit-reproducible. node-gyp writes the absolute build path and a random temp directory into the tree-sitter native objects, and the renderer bundle copies embed the random upstream extraction directory. Any two builds therefore differ, even two builds of one tree in two worktrees.

The rebuilt asar was compared with the build the independent verifier checked, file by file. Both hold 1337 files with none added or removed. Five differ, all of them the two causes above. The patched chunk view-B5Ug8wEm.js and the patched stylesheet index-lCyB53CO.css are byte for byte identical. The guards were then re-run against the newly deployed asar, and the deployed build was driven through the marketplace to a plugin detail page.

The deployed asar sha256 is b13738658d4f1096fc6854fb6621e31bf38418985d2e42d7ed9d7f7a19790a04.

@tyonger-stack
tyonger-stack force-pushed the feat/marketplace-manage-page-0781 branch from e6b4f92 to ea1af35 Compare November 1, 2026 20:38
@tyonger-stack
tyonger-stack force-pushed the feat/marketplace-detail-view-0781 branch 2 times, most recently from 0fe7340 to 48020ab Compare November 1, 2026 20:39
@tyonger-stack

Copy link
Copy Markdown
Owner Author

PASS+NOTES

Verified at head a4d5ea4b86f25d321e726226332f5c33158d7d8c against base 0b548c224bef19619f21ec9d6e1e09f2d131fd2b, in a clean detached worktree (wt-verify-27) with node_modules / src/app/dist APFS-cloned in. Node v26.5.1. Nothing was committed, pushed, merged or retargeted.

1. npm run check — PASS

typecheck exit 0, source:typecheck exit 0, test suite:

run tests pass fail skipped
before .build existed 2735 2698 0 37
after packaging 2735 2701 0 34

The 3-test delta is not a flake: tests/plugins-marketplace-renderer-patch.test.mjs:235 (stagedCssSkip) and siblings skip on the absent packaging staging dir. src/app/dist was verified pristine before and after (both anchor probes = 1).

2. The package builds — PASS

node -e "require('fs').rmSync('.build',{recursive:true,force:true})"
node scripts/package-macos.mjs

exit 0. Tail:

Marketplace manage page: official 0.78.1's second-level page applied (view-B5Ug8wEm.js).
Marketplace manage-page CSS: official 0.78.1 page rules added (index-lCyB53CO.css, 23 of 42 appended; 42 classes lifted).
Marketplace detail view: official 0.78.1 plugin detail page added (view-B5Ug8wEm.js).
Marketplace detail view CSS: official 0.78.1 rules added (index-lCyB53CO.css, 15 of 38 appended).
...
Fidelity hybrid ASAR ready: /Users/Apple/Documents/grokbot/wt-verify-27/.build/fidelity/app.asar
Packaged application: /Users/Apple/Documents/grokbot/wt-verify-27/dist/Grok Node.app (6 native manifest entries, 773 unpacked runtime files)

15 of 38 matches the doc's claim exactly.

3. The six official-only rules ship standalone, byte for byte — PASS

In .build/fidelity/app/dist/renderer/assets/index-lCyB53CO.css each of the six is present as exactly one standalone line (grep -Fxc = 1 for each), and each rule text is a byte-identical substring of official's own rea-grokbot-0781/app/dist/renderer/assets/index-Dh7EWA8t.css:

class standalone lines byte-identical to official
sand-1lun4ml 1 yes
sand-pilrb4 1 yes
sand-18b5jzi 1 yes
sand-1o3jo1z 1 yes
sand-v5lvn5 1 yes
sand-4meti 1 yes

Stronger: all 38 rules in scripts/lib/marketplace-detail-view-0781-official.css are both byte-identical to official and standalone in the staged stylesheet (38/38, 0 failures). Using the repo's own scope-aware resolver (marketplaceManagePage0781ClassesStyledInDialog, DIALOG_CLASS = "sand-plugins-dialog"), all six resolve inside the plugins dialog — i.e. the unscoped rule reaches the dialog and is not merely shadowed. 169/169 class tokens in the port's injected source resolve there as well.

4. The injector fix is real — PASS (mutant goes red)

Reverted the presence check in scripts/lib/marketplace-detail-view-0781-css-patch.mjs to the old substring form:

const missing = rules.filter((rule) => !original.includes(rule));

node --test tests/marketplace-detail-view-0781.test.mjs → 37 tests, 36 pass, 1 fail, with the fail-closed guard firing:

✖ the CSS patch ships a standalone rule even when a scoped rule names the same class
  Error: Marketplace detail view CSS patch: 2 official rule(s) are not present as standalone
  rules in index-scoped.css: .sand-1lun4ml:not(#\#)… | .sand-pilrb4:not(#\#)…

This matches the doc's "36 pass / 1 fail" exactly. The file was restored from a distinct backup (/tmp/verify27-css-patch-ORIGINAL-21917.mjs); sha256 is back to 77595ff9286ced408d240476c0daf9a7b8afd93efdc9ef501e44b7bd7da88fdc and git status is empty.

5. Every string comes from official's locale tables — PASS

Cross-checked all 55 message ids in tests/fixtures/official-0781-detail-view-messages.json against official's own locale chunks (index.eager-common-DbK3Oi_r.js for en, chunk-core-CXBwRBzw.js for zh): the ICU arrays are structurally identical on both sides — 55/55 exact, 0 mismatches, 0 missing. The 8 ids this PR adds (CzixCu, FGnQEW, RDjuBN, bPwFdf, bWyJ+b, kDCdbL, mrRDVU, xdA/+p) are present in official's own tables with the same text on both sides.

6. The shipped chunk parses, no i18n defect — PASS

node --check passes on 102 of 102 .js files under .build/fidelity/app/dist/renderer/assets/, including view-B5Ug8wEm.js. The known defect signature "(RLocT(" occurs 0 times in the built assets (the 1113 raw RLocT( hits are ordinary calls).

7. Nothing unrelated rode along — PASS

git diff --stat base..head shows exactly six files: the doc, the detail-view patch module, its css patch module, its official css, the messages fixture, the detail-view test. 756 insertions / 14 deletions. No source, no lockfile, no unrelated file.

8. The injector defect, resolved from the build's own bytes — the PR's "two" is CORRECT

Reconstructing the pre-patch stylesheet from the staged file (the 15 appended rules sit contiguously at lines 1444–1458) and running both algorithms on those bytes:

  • old substring check → appends 10 of 38
  • new line-exact check → appends 15 of 38
  • delta = 5 rules the old check wrongly skipped: sand-1lun4ml, sand-pilrb4 (shadowed by .r-conversation-computer-card .sand-X{…}) and sand-37c5m6, sand-1qab1bc, sand-ibwnj (shadowed by :where(.sand-plugins-dialog) .sand-X{…}).

Of the six rules this PR adds, exactly two were actually swallowed and never shipped: sand-1lun4ml and sand-pilrb4. So the PR body and the doc are right, and the fix is exactly as scoped.

Correcting an intermediate claim of my own: I first suspected three, counting sand-18b5jzi. That is wrong. sand-18b5jzi is shadowed by the card rule, but the unscoped rule was already present as a standalone line in the pre-patch stylesheet, so it shipped; the old check skipped it only because the scoped text happened to match as a substring. Same for sand-1o3jo1z. sand-v5lvn5 and sand-4meti were never shadowed at all (the card's sand-v5lvn5 copy declares transparent, not official's #0000).

Why only the two mattered: the card scope .r-conversation-computer-card does not name the plugins dialog, so that shadow never reached the detail page's 编辑值 button. The other three shadows are :where(.sand-plugins-dialog), which does name the dialog, so those rules kept styling the dialog correctly. The PR's account of the defect is accurate.


Notes (documentation only — nothing functional)

  1. Two different npm run check numbers in one PR. The PR body records "2697 pass, 0 fail and 37 skipped"; the doc's deployment table records "2700 pass, 0 fail, 34 skipped". I measured 2698/0/37 (pre-.build) and 2701/0/34 (post-.build). The split depends on whether the packaging staging dir exists, so both recorded figures sit in the observed band and both are 0-fail — but they disagree with each other. Worth settling on one, or recording the condition.

  2. "all 37 class tokens" is not reproducible as stated. The substantive claim — every class token the ported recipes use resolves — is true, and I confirmed it against the staged stylesheet: 66/66 style-bearing tokens written into the chunk, 59/59 for the recipes this PR adds, 169/169 for the port's injected source (excluding the 5 stylix namespace markers), 41/41 classes in the detail companion CSS. I could not reconstruct a set of exactly 37; please state which set that number refers to.

  3. Pre-existing stale comment, not from this PR. scripts/clean-build.mjs:539 still reads "The 21 official 0.78.1 detail-page rules upstream 0.18's stylesheet does not define." while the companion now carries 38 rules and the build appends 15. That line is unchanged from the base (git show base:scripts/clean-build.mjs is identical), so this PR did not introduce it — flagging it because it now understates the payload and is the kind of comment that misleads the next reader. I did not edit it.

Tian and others added 4 commits November 2, 2026 09:38
The detail page now renders official's section heading, card, row, account
title, tools summary, chevron and small secondary button recipes instead of
upstream 0.18's, and every string it shows comes from official's own locale
tables.

The CSS injector dropped two official rules. It decided a rule was already
present with a substring search, and this repository's own computer-card patch
ships a scoped rule that contains the unscoped one as a substring. The
unscoped rules for sand-1lun4ml and sand-pilrb4 never shipped, so the Setup
section's 编辑值 button rendered without its border widths. The injector now
compares whole lines and fails closed when an official rule is missing as a
standalone rule.
Documents the recipes the port writes into the chunk, the CSS injector fix,
the per-plugin pixel diff over the seven plugins both apps share, and the
differences that remain with their causes.
The independent verifier flagged two documentation numbers that did not line up.

The suite is 2735 tests. Three of them read the packaged staging directory, so
the split depends on whether that directory is present: 2698 pass and 37
skipped without it, 2701 pass and 34 skipped with it. The PR body and the port
record each quoted one of the two without saying which state it was, so the
record now states both.

The build script's comment on the detail-view CSS step still said "21 rules"
from the earlier wave. The companion carries more now and the number the step
appends depends on what the staged stylesheet already holds, so the comment
describes the mechanism instead of a figure that drifts.
…age wave

The manage wave landed first, so the detail wave was rebased onto it and
rebuilt. The rebase moved two files: this document and a comment in
scripts/clean-build.mjs.

The packaged asar is not bit-reproducible, so the rebuilt asar is compared
with the build the independent verifier checked at the content level. Both
hold 1337 files with none added or removed. Five differ: three renderer
bundle copies carry the random upstream extraction directory, and two hash
manifests record the tree-sitter native objects that node-gyp rebuilt with
the other worktree's absolute path. The patched chunk and the patched
stylesheet are byte-for-byte identical.

The guards were re-run against the newly deployed asar and the deployed
build was driven through the marketplace to a plugin detail page.
@tyonger-stack
tyonger-stack force-pushed the feat/marketplace-detail-view-0781 branch from 48020ab to 9393f8e Compare November 2, 2026 01:47
@tyonger-stack
tyonger-stack changed the base branch from feat/marketplace-manage-page-0781 to main November 2, 2026 01:47
@tyonger-stack
tyonger-stack merged commit 0f3a56a into main Nov 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant