') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); refactor(frontend): simplification batch 2 — mounted-guard sweep + app-shell derived-value extraction (Rounds D-2 + E) by jackwener · Pull Request #887 · apache/maka · GitHub
Skip to content

refactor(frontend): simplification batch 2 — mounted-guard sweep + app-shell derived-value extraction (Rounds D-2 + E) - #887

Merged
jackwener merged 9 commits into
mainfrom
chore/frontend-simplify-batch-2
Jul 13, 2026
Merged

refactor(frontend): simplification batch 2 — mounted-guard sweep + app-shell derived-value extraction (Rounds D-2 + E)#887
jackwener merged 9 commits into
mainfrom
chore/frontend-simplify-batch-2

Conversation

@jackwener

Copy link
Copy Markdown
Member

One batched PR for the remaining two rounds of notes/frontend-simplification-map-2026-07-13.md (Rounds A/B/C/D-1 landed earlier as #867/#876/#869/#871/#877).

Round D-2 — mounted-guard long tail (34 sites)

Every remaining hand-rolled mounted-guard converts to the shared useMountedRef from @maka/ui: 20 renderer settings sites, 4 other renderer sites, 10 packages/ui panels. Each site keeps its ref name and its companion-ref cleanup effect; the whole effect is deleted only where it did nothing but the flag (browser-panel, permission-dialog). ~30 contract assertions across ~20 test files re-pinned to the shared-hook shape — no assertion deleted. The useRef(false) variants were verified to read the flag only inside async handlers, so true-initial semantics are behavior-preserving. Deliberately left: use-memory-settings-controller and use-workspace-instructions-controller (lifecycle-counter variants, not boilerplate) and app-shell's rendererMountedRef.

Round E — app-shell derived-value extraction (Round B follow-on)

app-shell.tsx 1680 → 1562 lines. The ~210-line derived block moved into two pure-derivation hooks, every memo keeping its exact dependency array and referential stability:

JSX return split was evaluated and skipped with documented rationale in the map: every meaningful chunk is pinned to app-shell.tsx by direct-read behavioral contracts, and extraction would net ~50-110 props of pass-through drilling — more boilerplate, not less, under the zero-behavior mandate.

Merge notes

Integration branch absorbed three concurrent main advances; conflicts resolved keeping both sides' intent: settings-surface (#875 provider-catalog effect + hook conversion), permission-dialog (#881 PermissionPrompt rename + denyButtonRef + hook conversion, contract pins re-merged to prompt-naming + hook shape).

Gates (merged tree, after all conflict resolution)

desktop 2409/2409 · ui 125/125 · full typecheck · knip ×2 = 0 · check-dead-css clean · alignment auditor all fixtures clean. Per-round CDP branch-vs-baseline captures during development: zero visual change (only known-environmental diffs: live git-branch chip label, capture-flaky settings-general baseline).

…und D-2)
Swap the hand-rolled mounted-guard boilerplate (ref set true on mount,
false on unmount) for the shared useMountedRef hook across 20 renderer
settings sites, keeping each site's ref name and its companion-ref
cleanup effect. Re-pin the 13 contract suites that quote the old
definition/effect shape to the shared-hook form.
use-memory-settings-controller stays local: its cleanup reset is guarded
by a lifecycle counter and reads combine mounted with lifecycle equality
(lifecycle-counter variant, same shape as use-workspace-instructions-
controller), so it is not boilerplate.
…(Round D-2)
Convert OnboardingHero readyHero, FirstRunChecklist, artifact-pane, and
browser-panel to useMountedRef. browser-panel's mount effect did nothing
but the flag, so the whole effect is deleted (its reads live in an async
callback, so the true-initial hook is behavior-preserving). Re-pin the 4
contract suites and mark the Round D-2 map bullet shipped.
…d D-2)
Convert chat-turn, chat-model-switcher, search-modal, plan-reminder-panel,
clipboard-feedback, skills-panel, composer, permission-dialog,
session-history-list, and daily-review-panel to useMountedRef, imported
from ./use-mounted-ref.js per intra-package house style. permission-dialog's
mount effect did nothing but the flag, so the whole effect is deleted. Re-pin
the 10 contract suites (definition + effect blocks) to the shared-hook form.
…to chore/frontend-simplify-batch-2
# Conflicts:
#	apps/desktop/src/renderer/settings/settings-surface.tsx
#	notes/frontend-simplification-map-2026-07-13.md
…tions (Round E blade 1)
Move the model/thinking selection cluster (chatModelChoices, active/new-chat
model+label, thinking-variant lists, sticky-pick validation, both pending
new-chat states) and the two chat-header alert memos out of app-shell.tsx into
a new pure-derivation hook use-shell-chat-model.ts. openSettingsSection is
injected so chatConnectionAlert keeps wrapping the derived click target with
its identical (exhaustive-deps-excluded) dep array. Every memo keeps its exact
dependency array so chatModelChoices / activeThinkingLevels / newChatThinkingLevels
retain referential stability. Zero behavior change.
app-shell.tsx 1680 -> 1585. Re-pinned: added use-shell-chat-model.ts to the
renderer-shell-source combined allowlist and to the composer-new-chat model
picker contract's subset reads (pendingNewChatModel / validPendingNewChatModel /
newChatThinkingLevel declarations moved into the hook).
…ound E blade 1 cont.)
Move the live-turn derivation sub-cluster (activeShellRunUpdates, streaming/
thinking text slices, streamingSessionIds pulse set, liveTools/hasInFlightLiveTools,
and the #646 turnInFlight / sessionAwaitingModel / showProcessing / showContinuing
wait cues) out of app-shell.tsx into use-shell-live-turn.ts. activeLiveTurn keeps
its pinned declaration in app-shell.tsx (streaming-timeline contract) and is passed
in; every memo keeps its exact dependency array so referential stability is
unchanged. Zero behavior change.
app-shell.tsx 1585 -> 1562. Added use-shell-live-turn.ts to the renderer-shell-source
combined allowlist so the session-event-health / status-presentation combined-source
contracts keep seeing the moved hasInFlightLiveTools memo.
…nto chore/frontend-simplify-batch-2
# Conflicts:
#	notes/frontend-simplification-map-2026-07-13.md
…fy-batch-2
# Conflicts:
#	apps/desktop/src/main/__tests__/permission-response-guard.test.ts
#	apps/desktop/src/main/__tests__/permission-response-ipc-boundary.test.ts
#	packages/ui/src/permission-dialog.tsx
@jackwener
jackwener merged commit 8f7f357 into mainJul 13, 2026
3 checks passed
@Astro-Han
Astro-Han deleted the chore/frontend-simplify-batch-2 branch July 14, 2026 05:05
Astro-Han added a commit that referenced this pull request Jul 16, 2026
* docs: retire tracked notes into the archive
notes/ regrew tracked files after the archive README retired it as an
undocumented parallel authority. Move the simplification baseline map
(#871-#887) and the shipped composer-mentions v1 spec (#979) into
docs/archive/, register them under Former repository notes, and point
the citing source comments at the archived path.
* docs: archive computer-use chronicles and research records
The #857-#985 computer-use chain left one root document per PR:
follow-up fix records, an incident investigation, and run logs that
duplicate the kept contracts. Archive the seven chronicles, mark the
foundation contract validation matrix as the #857 split-gate baseline
(current state lives in source and contract tests), and register each
archived file in the archive README with a pointer to its current
authority.
Also archive the WorkBuddy/QoderWork reverse-engineering records (the
shipped design contract stays at docs/expert-team-runtime.md) and the
synthesis-cache benchmark log (progress belongs in issues #481/#578),
and fix the two surviving links to the moved paths.
* docs: map current contracts in the documentation README
Seventeen root documents existed outside the authority map with zero
incoming links. After archiving the chronicles, list the surviving
computer-use contracts and the expert-teams runtime contract, and
write down the maintenance rule that PR follow-up records, incident
investigations, and run logs belong in pull requests or the archive —
with notes/ and docs/local/ as untracked local scratch.
Sign up for freeto 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

@jackwener