Skip to content

One module-alias owner: package.json electron dependency alias (X02) vs a Bun preload plugin for the five Electron specifiers (X03) #412

Description

@0monish

Generated by an AI agent (Claude Code, Fable 5.1) on behalf of @0monish during Wayfinder charting of the Electron compatibility program, 2026-10-06. Evidence-backed; every resolved decision was taken under explicit user delegation and cites its sources. Planning only — no implementation is authorized by this issue.

Parent map: #391 · Unit: X02 (migrate-tooling) · Wayfinder type: grilling · Status: open (not resolvable from current evidence)

Question

The refuter proved tsconfig paths does not reach a node_modules dependency's require("electron"); a package.json dependency alias does on Bun 1.4.2. X03 proposes a Bun plugin to also cover electron/main|renderer|common|utility. Recommendation: package.json alias as the single runtime resolver (bundler-neutral) with package exports for the subpaths; a plugin only if exports cannot express them. Decide and fix the arch 04 §2 bunfig wording.

What is known / why it is still open

No evidence-backed resolution yet; see the unit research note for the proposed answer and refuter verdicts.

Context

Epic #496 · research note wayfinder/electron-compat/notes/X02.md on the research branch.

Activity

  1. added theissue type on Oct 6, 2026
  2. 0monish commented on Oct 6, 2026

    @0monish
    MemberAuthor

    Generated by an AI agent (Claude Code, Fable 5.1) on behalf of @0monish, 2026-10-06, under the map's execution doctrine. Statements are labelled FACT / INFERENCE / UNKNOWN by their author; nothing here authorizes implementation.

    Decision packet

    Decision: Which single mechanism resolves 'electron' and 'electron/main', 'electron/renderer', 'electron/common', 'electron/utility' to @keld/electron in a migrated app's Bun main role (package.json dependency alias with package exports, a Bun preload plugin, or tsconfig paths), and what architecture 04 sections 2 and 3 say afterwards.

    Classification: decided · Milestone (YAGNI test against the first proof): first-proof · Reversible: Yes. It is one package.json line plus package exports; switching to a plugin later changes no wire format, permission or host contract. The arch 04 wording changes through a spec PR. · Owner: Architecture 04 (docs/architecture/04-electron-compat.md), whose spec owner is KEL-17 (Done, assignee GYLDLAB), and the packages/@keld/electron package from KEL-72 (Done, unassigned); Linear fetched 2026-10-06. Neither is open, so the live tracking surface is #412 under map #391. The reserved migrate verb points to KEL-17.

    Facts

    Inferences

    • All three mechanisms can resolve the five names on Bun 1.4.2, so the choice is decided by ownership and failure mode, not by capability.
    • The plugin and tsconfig mechanisms leave the real electron package installed and fail silently when not in force (wrong working directory, Node-run script): the app receives a path string instead of the API. A dependency alias makes node_modules itself the truth, so every resolver agrees.
    • Package exports can express Electron's contract: map all five specifiers to one file. Mapping import and require conditions to different files would create two module instances and split the app singleton, so one file is required.
    • CommonJS require of an ESM entry works on Bun and Node 26 only without top-level await. That matches the already-resolved rule that boot-static values are synchronous at import.
    • Under real Electron the builtin resolver wins before node_modules, so an Electron-arm fixture is unaffected by the alias. Not run.
    • With types supplied by the aliased package, migrate has no reason to write tsconfig paths, and bunfig.toml loses its only stated purpose.

    Unknowns

    • Whether the real @keld/electron resolves through the alias from draw.io's actual dependency set. It cannot be tested until the package is self-contained.
    • Whether Bun auto-install honours a package.json alias when node_modules is absent.
    • Whether a transitive package that lists electron under dependencies would bring a nested real electron.
    • tsc and webpack resolution through the alias. Not tested by anyone.
    • Whether a workspace-style spec can alias the name 'electron' inside the Keld monorepo fixtures.

    Alternatives

    Option Cost New invariant created Existing invariant at risk
    A. package.json dependency keyed 'electron' pointing at @keld/electron (npm: once published; file: or link: before), with package exports mapping all five specifiers to one entry. @keld/electron must become an installable, self-contained package with one require()-able entry and four subpath exports. migrate must rewrite or remove 'electron .' and electron-builder scripts in the same edit. An installed-tree check is needed (exactly one electron, and it is the shim; Bun auto-install detected or disabled). node_modules/electron is @keld/electron; all five specifiers and both module systems resolve to one file; no runtime resolver hook exists. The 'five files, nothing else' promise if the script rewrite is not done in the same edit; correctness if a nested real electron goes undetected.
    B. Bun preload plugin for the five specifiers (the X03 proposal). A Keld-owned hook in every role. Observed today: loaded by working directory through bunfig.toml and silently absent otherwise; Bun-only, so types and Node-run scripts need a second mapping; the real electron package stays installed. Every role starts with the alias preload active, which the host would have to enforce on the role command line. One rule, one owner (plugin for runtime plus tsconfig for types); loud failure (it degrades to the wrong module silently); the host spawn path would carry a compat concern.
    C. tsconfig paths (today's KEL-72 v0 mechanism). No new code. Bun-only. A JavaScript app such as draw.io has no tsconfig, so migrate would edit a file outside arch 04 section 2's table. The X02 refuter reported one intermittent failure when a CommonJS dependency required the TypeScript ESM shim through it. tsconfig is a runtime input. The five-file contract; Node-run consumers silently get the real electron package.
    D. Ship A and B together. Two resolvers that can disagree. None. Root AGENTS rule that parallel copies and diverging fallback paths are defects.

    Recommendation

    Choose A as the single resolver; no plugin and no bunfig alias. Record it in arch 04 section 2 (the package.json row carries the 'electron' dependency; the bunfig.toml alias row is removed) and section 3 item 1 with its v0 note, inside the X02-T1 (#497) spec PR. X03-T1 (#502) adds the four subpath exports to the one entry. The KEL-72 fixtures keep tsconfig paths only until @keld/electron is consumable as a package, then switch to the same dependency form. Evidence that determines it: Electron's own one-resolver contract, the working-directory and Node probes re-run today showing B and C fail silently, and arch 04 section 2 already admitting the package.json edit. Any further use of bunfig.toml (for example disabling auto-install) is a separate decision.

    Falsifier: With draw.io's four packages at the corpus-pinned versions installed beside an 'electron' dependency alias pointing at an @keld/electron-shaped package (ESM, one entry, exports for five specifiers), any of the following on Bun 1.4.2: a specifier form (ESM default, ESM named, CommonJS require, any subpath) from app code or a dependency not resolving to the shim; require of the entry failing in any of 20 runs; or require('electron').app and (await import('electron')).app being different objects. Any of these means exports cannot express the contract, and the plugin (with a host-passed preload) is reopened.

    Missing evidence: The positive dependency-alias arm executed against the real @keld/electron and draw.io's real dependencies (blocked until the package is self-contained); tsc and webpack resolution; Bun auto-install behaviour with the alias declared but node_modules absent. These are acceptance checks for X03-T1 (#502) and X02-T3 (#499), not blockers of the choice.

    Next action: Orchestrator records the decision on #412, citing the working-directory probe, and the X02-T1 (#497) (#497) spec author carries the arch 04 sections 2 and 3 erratum in that spec PR for exact-content owner approval. First check: #412 reads resolved with the probe cited, and the spec PR's arch 04 section 2 table no longer names bunfig.toml as the alias file.

  3. added
    milestone:first-proofNeeded for the first migration proof (drawio-desktop on macOS, explicit legacy profile)
    on Oct 6, 2026
  4. 0monish commented on Oct 6, 2026

    @0monish
    MemberAuthor

    Generated by an AI agent (Claude Code, Fable 5.1) on behalf of @0monish, 2026-10-06, under the map's execution doctrine. Statements are labelled FACT / INFERENCE / UNKNOWN by their author; nothing here authorizes implementation.

    Resolution

    Choose A as the single resolver; no plugin and no bunfig alias. Record it in arch 04 section 2 (the package.json row carries the 'electron' dependency; the bunfig.toml alias row is removed) and section 3 item 1 with its v0 note, inside the X02-T1 (#497) spec PR. X03-T1 (#502) adds the four subpath exports to the one entry. The KEL-72 fixtures keep tsconfig paths only until @keld/electron is consumable as a package, then switch to the same dependency form. Evidence that determines it: Electron's own one-resolver contract, the working-directory and Node probes re-run today showing B and C fail silently, and arch 04 section 2 already admitting the package.json edit. Any further use of bunfig.toml (for example disabling auto-install) is a separate decision.

    Falsifier (reopen if observed): With draw.io's four packages at the corpus-pinned versions installed beside an 'electron' dependency alias pointing at an @keld/electron-shaped package (ESM, one entry, exports for five specifiers), any of the following on Bun 1.4.2: a specifier form (ESM default, ESM named, CommonJS require, any subpath) from app code or a dependency not resolving to the shim; require of the entry failing in any of 20 runs; or require('electron').app and (await import('electron')).app being different objects. Any of these means exports cannot express the contract, and the plugin (with a host-passed preload) is reopened.

    Resolved under the user's delegation on the evidence in the decision packet above, after independent refutation of the underlying research. Reopen by comment with contrary primary evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    electron-compatElectron compatibility program areamilestone:first-proofNeeded for the first migration proof (drawio-desktop on macOS, explicit legacy profile)wayfinder:grillingWayfinder human decision

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions