Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(desktop): harden core barrel against node-only value exports by sunheyi6 · Pull Request #1734 · apache/maka · GitHub
Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(desktop): harden core barrel against node-only value exports by sunheyi6 · Pull Request #1734 · apache/maka · GitHub
Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', '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('^' + ".*" + ' fix(desktop): harden core barrel against node-only value exports by sunheyi6 · Pull Request #1734 · apache/maka · GitHub
Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han
, '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" + ' fix(desktop): harden core barrel against node-only value exports by sunheyi6 · Pull Request #1734 · apache/maka · GitHub
Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han
, '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('^' + ".*" + ' fix(desktop): harden core barrel against node-only value exports by sunheyi6 · Pull Request #1734 · apache/maka · GitHub
Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han
, '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); } })(); })(); fix(desktop): harden core barrel against node-only value exports by sunheyi6 · Pull Request #1734 · apache/maka · GitHub
Skip to content

fix(desktop): harden core barrel against node-only value exports - #1734

Merged
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary
Aug 8, 2026
Merged

fix(desktop): harden core barrel against node-only value exports#1734
Astro-Han merged 3 commits into
apache:mainfrom
sunheyi6:codex/fix-desktop-startup-node-boundary

Conversation

@sunheyi6

@sunheyi6sunheyi6 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Defensive hardening of the renderer-facing @maka/core barrel: the browser-consumed barrel no longer value-exports any module whose implementation depends on node:*, and an executable regression guard prevents the Node-only export graph from returning to the renderer entry path.

Scope (per review 4bd7b29a, re-scoped from "fix" to defensive hardening — the white-screen mechanism was not reproducible under the pinned Vite 8.1.5 toolchain, where tree-shaking removes the node:* references and dev-mode proxies throw only on call, not on import):

  • packages/core/src/index.ts — drop value exports for tool-ledger-scanner (node:util), tool-args-identity (node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle (node:crypto); keep only type exports in the barrel. The explicit subpaths (@maka/core/tool-args-identity, @maka/core/tool-ledger-scanner, @maka/core/canonical-runtime-event, @maka/core/tool-recovery-bundle, @maka/core/runtime-boundary) already exist in package.json exports and now carry the value consumers (runtime, storage, runtime-host).
  • apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts (+ fixtures) — re-lands the regression guard in executable form against the built barrel artifact the renderer actually consumes: a child Node process registers a loader hook that throws on every node:* import and then imports @maka/core; it exits non-zero the moment the barrel graph evaluates Node-only code. This replaces the source-regex contract pruned by chore: prune source-regex tests and parallelize the e2e suite #1727.

Why defensive

Under the pinned toolchain the production renderer bundle tree-shakes the node:* references and dev mode never calls the proxied functions, so there is no current white screen — but the invariant ("importing @maka/core in a browser-like environment evaluates no node:* module") relied on tree-shaking luck rather than construction. Keeping Node-only values behind explicit subpaths makes the boundary structural and test-enforced.

Validation

  • npm test (full suite: clean + build:test + script tests + all workspace test:dist)
  • new regression guard passes: importing built @maka/core evaluates no node:* module
  • Biome check and git diff --check

@sunheyi6
sunheyi6 marked this pull request as ready for review August 1, 2026 00:13

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head. Moving runtime-boundary values to the existing subpath fixes the renderer import boundary without adding a second implementation. The renderer build and CI coverage are appropriate. No findings.

The branch currently conflicts with main, so the resolved head will need another review.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review findings (independent deepseek-v4-flash review, 2 passes)

The fix itself (moving runtime-boundary value exports out of the core barrel) is correct and mechanically complete — but the earlier approval no longer covers the head (the merge commits changed the branch), and two P2s need a decision.

P2 — the startup contract test you added was swallowed by the merge; the head has no regression guard

startup-loading-shell-contract.test.ts (3 tests added in 6da3471be, including the barrel-purity assertion) was deleted on main by #1727 and the merge commit fc099b75 kept main's deletion — git ls-tree 4bd7b29a has no such file. The PR body's "startup loading shell contract: 3 passed" verification is therefore not reproducible on the current head, and the exact #1573 regression class this PR fixes can silently return. Please re-land the contract in an executable form (e.g. assert the renderer build output contains no node: imports rather than a source-regex test), or explicitly defer with a reason.

P2 — the barrel still value-exports 3 other Node-only modules; the new comment overstates the invariant

packages/core/src/index.ts:255-260 (tool-ledger-scanner → node:util), :291 (tool-args-identity → node:crypto), :292-295 (canonical-runtime-event → node:util), and :285-290 (tool-recovery-bundle → node:crypto) are still value-exports, while :304-306 claims "renderer imports of @maka/core do not evaluate Node-only modules". Today the renderer graph happens to tree-shake them (verified: 0 node: references in the production bundle; dev-mode Vite uses a browser-external proxy that only throws on call, not on import), so there is no current white screen — but the fix relies on luck, not construction. Either move the remaining Node-only value exports behind subpaths (the subpaths already exist in package.json exports), or correct the comment to state the actual invariant.

Needs discussion — the root-cause mechanism is not reproducible with the pinned toolchain

We rebuilt the PR base (barrel with runtime-boundary value export), the head, and the fix-parent state with the pinned Vite 8.1.5: the production renderer build succeeds in all three states with zero node: references (tree-shaken), and dev mode does not throw on module evaluation (the proxy throws only when a function is called; the renderer never calls them). Current main re-added all four value exports and the renderer still works. If the mechanism is "barrel evaluation of node:crypto throws before createRoot", it doesn't hold under the pinned toolchain — the white screen you observed may have a different root cause, and this PR may be defensive hardening rather than the fix. Please reproduce the original white screen on a clean environment with the pinned toolchain (with bundle evidence), or re-scope the PR as defensive hardening.

Gate: no P0/P1 → not a FAIL; the two P2s need to be handled (fix or explicit deferral) before merge.

@sunheyi6sunheyi6 changed the title fix(desktop): prevent startup white screenfix(desktop): harden core barrel against node-only value exportsAug 3, 2026
@sunheyi6

Copy link
Copy Markdown
ContributorAuthor

Merged latest main (incl. upstream 13cf3e6) into the branch and resolved all conflicts — the PR is now mergeable.

Conflict resolution notes:

  • packages/core/src/index.ts: kept this PR's hardening (Node-only value exports stay type-only/absent in the barrel) against main re-adding them
  • packages/storage/src/agent-run-store.ts: kept both the PR's subpath imports (canonical-runtime-event, tool-ledger-scanner) and main's new orchestration imports
  • execution-stores.test.ts: deleted upstream (refactor(storage): make SQLite the sole operational authority #1994) — the PR's import migration on it is moot, deletion kept
  • New consumers main/upstream introduced for the removed barrel values were migrated to subpaths: ai-sdk-backend.ts (stripUndefinedDeep → @maka/core/tool-args-identity), runtime-host execution-host tests (canonicalToolArgsHash → subpath), conversation-copy test (canonicalToolArgsHash → subpath, workspace store import per upstream)

The two P2s from the review are addressed on the head:

  • P2 regression guard: re-landed in executable form — apps/desktop/src/main/__tests__/renderer-core-barrel-node-boundary.test.ts spawns a child Node process with a loader hook that throws on any node:* import, then imports the built@maka/core barrel; passes locally (1/1)
  • P2 remaining Node-only value exports: tool-ledger-scanner, tool-args-identity, canonical-runtime-event, tool-recovery-bundle are now type-only (or absent) in the barrel; value consumers route through the existing subpaths

Local validation: full build:test clean, core suite 772/772, ai-sdk-backend 175/175, barrel regression guard passes, biome lint clean. (Storage/runtime-host sqlite & git-marker tests fail on this Windows box due to temp-dir junction/EBUSY lock issues — pre-existing environment noise, unaffected by this PR.)

sunheyi6 added a commit to sunheyi6/maka-agent that referenced this pull request Aug 4, 2026
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks — the revised direction looks sound. Moving Node-only value exports behind the existing subpaths keeps the renderer-facing @maka/core root browser-safe without introducing a parallel implementation, and the built-artifact loader guard is the right level of protection.

The earlier review concerns appear resolved. The remaining work is mainly integration with current main:

P2 — Please rebase and preserve the browser-safe root invariant while resolving conflicts

This branch now conflicts with main, which has since added or restored more root-barrel values and consumers, including Node-dependent paths. A mechanical conflict resolution could either reintroduce the renderer boundary problem or remove exports that current consumers need.

Please rebase onto the latest main, move any newly exposed Node-only values to their existing subpaths as needed, and make sure the built-artifact guard still passes on the resulting tree.

P3 — The test comments overstate the reproduced failure mechanism

The comments currently say that Vite imports of node:* fail before createRoot() and that the loader hook mirrors the renderer. The PR description now correctly treats this as defensive hardening rather than a confirmed reproduction of the original white-screen mechanism.

It would be more accurate to describe the test as intentionally enforcing a stronger structural invariant: the renderer-facing root barrel must remain loadable without Node built-ins, regardless of current tree-shaking behavior.

The unused FIXTURES_DIR constant can also be removed while touching the test.

The implementation itself does not need another redesign. After the rebase and a fresh CI run, this should be ready for another quick review. Thanks!

Drop value exports for tool-ledger-scanner (node:util), tool-args-identity
(node:crypto), canonical-runtime-event (node:util), and tool-recovery-bundle
(node:crypto) from the browser-consumed @maka/core barrel; keep type exports
and route value consumers to the explicit subpaths. Re-lands the renderer
regression guard as an executable test against the built barrel.
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from a102889 to b4c8657CompareAugust 8, 2026 08:05
…#2258
- shell-run.ts gained a node:util dependency in apache#2258; replace the single
isDeepStrictEqual use with a local structural comparison so the
renderer-facing @maka/core barrel stays free of node:* evaluation
- migrate main's new barrel consumers of node-only values to their
existing subpaths (tool-args-identity, tool-ledger-scanner,
canonical-runtime-event)
- reword the barrel boundary test comments to describe the enforced
structural invariant instead of a reproduced failure mechanism;
drop the unused FIXTURES_DIR constant
@sunheyi6
sunheyi6force-pushed the codex/fix-desktop-startup-node-boundary branch from b4c8657 to 03f8199CompareAugust 8, 2026 09:38
@Astro-Han
Astro-Han merged commit da3d18c into apache:mainAug 8, 2026
12 checks passed
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.

2 participants

@sunheyi6@Astro-Han