You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
program(migrate): read-only analyzer, one package-manifest alias, a hand-authored draw.io first-proof artefact, a report without percentages, and the electron-apps-v0 product corpus #496
Generated by an AI agent (Claude Code) on behalf of @0monish during Wayfinder charting of the Electron compatibility program; rewritten 2026-10-07 by the doctrine-audit repair pass (change log at the end). Planning only — no implementation is authorized by this issue.
This epic covers keld migrate: read-only analysis by default and reversible writes only under --write. It also covers the one module alias an app needs (a package-manifest dependency keyed electron), the output contract for the Keld config files, the report wording, and the product corpus (electron-apps-v0) that scores real apps through the KEL-74 evidence schema. The first proof needs four slices from this epic: the output-contract spec (X02-T1), a hand-authored draw.io artefact that meets it (X02-T3), the corpus contract spec and manifest with red-until-implemented cells (X02-T5, X02-T4), and the scoring run on macOS (X02-T6), which is the only ticket that flips the corpus cells. The analyzer (X02-T7 spec, X02-T2 first slice, X02-T9 remaining blocker classes) and the --write generator (X02-T8) are next. The first proof does not need them: draw.io's channels and webPreferences can be enumerated by hand from one main file.
X02 owns no rows of the 2,128-member Electron v44.4.5 API matrix. Every API member is assigned to F01–F09. The entities X02 owns are the migration surfaces. Each one is either covered by a ticket below or listed under never / out_of_scope / not_yet_specified.
Corpus demand (resolved call sites, not token-scan leads)
FACT (corpus drawio-desktop@2edf9fb, grep 2026-10-07): the main file registers 24 distinct literal renderer→main channels through ipcMain.on/once. A 25th registration, log, is commented out. The preload forwards channel names chosen by the page, so the preload does not constrain the channel set. UNKNOWN: which of the 24 the web app actually sends, because the webapp submodule is empty in the clone. PANEL-P3 produces that list.
FACT (same commit): requestSingleInstanceLock() runs inside the app.whenReady().then callback, which is after ready. The published research said "pre-ready, same pattern as Zettlr", which is wrong for draw.io. Zettlr calls it before ready.
FACT (same commit): DRAWIO_DISABLE_UPDATE is read from process.env at module top level. autoUpdater.setFeedURL({provider:'github',…}) is called outside the disable guard. electron-updater, electron-store, electron-log and electron-context-menu all import the bare electron name.
FACT (same commit): shell.openExternal has two literal https origins (Help menu items) and one dynamic wrapper. app.getPath is called with userData and documents. disableBlinkFeatures is set on every window. The start script is electron ., five scripts run electron-builder, and the app has no tsconfig.
FACT (PANEL-D15, resolved counts): draw.io has 0 sendSync and 1 showMessageBoxSync, on the close path. Counts from the receiver-blind token scan (for example WebContents.replace 22, or the <webview> hits that are all webviewTag: false) are leads, not demand.
FACT (refuter receipt): Zettlr's forge config requires a git-hash helper that spawns a shell when the config is loaded, and its generateAssets hook spawns the pandoc download while packaging. This is why app configs are never executed.
Maturity ladder (owned by X01-EPIC)
BEHAVIOR_MATCH → CONFORMANCE_PASS → CORPUS_VERIFIED. Ticket targets: L0 = approved spec; L1 = implemented with tests on macOS; L3 = CORPUS_VERIFIED cells in electron-apps-v0 (panel product), with authority_profile: legacy_sandbox_off printed. Analyzer counts never become a cell: OperationKind is the closed set install / activation / primary_workflow / full_feature.
Linear owners consumed (Linear, fetched 2026-10-07; read-only)
KEL-17 "RFC: Electron compat layer and migration path": Done (GYLDLAB, 2026-07-10). The reserved migrate verb's tracking issue points here. Its acceptance criterion "keld migrate UX specified" closed without a spec file. The only UX text is the architecture 04 §1 sample, which X02-T1 corrects.
KEL-15 config RFC: Done (GYLDLAB). There is no schema text beyond architecture 04 §2 (comment d1137b07).
KEL-74 evidence schema and scorer: Done (GYLDLAB). DOCUMENTED_COMMITTED_PRODUCT_CORPORA is empty, so no product percentage can be printed.
KEL-237 lifecycle corpus: In Progress, unassigned. Its non-goals exclude product denominators and any expansion of the compatibility surface, so it is the pattern this epic reuses, not the owner. The orchestrator's bridge comment c13866bd records the separate electron-apps-v0 manifest.
KEL-127 program direction: Todo, unassigned. Its non-goals say it 'owns sequencing only; each code/spec concern gets its own issue', so it is the Linear reference for X02's migrate tickets, not their tracker of record. Its only attachment is the map Wayfinder map: KELD Electron Compatibility Program (Electron 44.x baseline) #391 link. It carries the sentence "analyzer starts read-only, reports compatibility/security/engine/native-dependency blockers separately and emits reviewable reversible changes only after authorization".
KEL-78 strict profile: In Progress (GYLDLAB). Its spec says the profile: "legacy" key "does not exist today", and none of its tasks T1–T7 names that key as a deliverable. On the map, X03-T5 owns the key's single location and grammar (a spec amendment under KEL-78) and X03-T7 owns its parser.
KEL-75 role spawn contract: In Progress, unassigned. FACT (KEL-75 spec at origin/main 29a4cd7): KELD_APP_LINK remains the sole child bootstrap variable, and a role-specific capability exception cannot arise from an environment value. KEL-102 guard enforcement: In Progress, unassigned. KEL-141 prebuilt distribution: Backlog, unassigned. KEL-103 signed macOS host: In Progress (Amisha Ramani).
Tracker of record (owner decision #517, adopted as X06-D7)
FACT (Linear, fetched 2026-10-07): no live Linear issue's scope covers X02. KEL-17 and KEL-19 are Done. KEL-237's non-goals exclude compatibility-surface expansion. KEL-127 owns sequencing only. So every X02 ticket's GitHub issue is its tracker of record. Linear references: KEL-127 for the migrate tickets (X02-T1, T2, T3, T7, T8, T9) and KEL-237 for the corpus tickets (X02-T4, T5, T6). Choosing KEL-237 as the nearest corpus surface is an INFERENCE.
Consequence: the X02 specs X02-T1, X02-T5 and X02-T7 are ready-for-agent. The feature and task tickets stay needs-spec because their specs have not landed, not because an owner is missing.
Design facts (labelled)
FACT (X02-A1, closed): there is one resolver, a package-manifest dependency keyed electron pointing at @keld/electron. It uses npm: once the package is published and file:/link: before that, with package exports mapping all five specifiers to one entry. There is no Bun plugin. The bunfig [alias] is inert on Bun 1.4.2, so migrate never writes it. tsconfig paths.electron gives Bun-only, silently wrong resolution and can create two module instances, so migrate never writes it and removes it if present. The arch 04 §2/§3 erratum lands in the X02-T1 spec PR.
FACT (refuter probes, Bun 1.4.2): @keld/electron is not consumable as a package today. It exports only ., as ESM TypeScript, and it imports @keld/api by a relative path outside the package. With no node_modules present, Bun auto-installs the real electron package and returns a string with no error. Owner of the self-contained, CJS-requirable entry, the subpath exports and the fail-closed role spawn: X03-T1 (adjacent atom, not X02). X02 owns only the manifest edit and the installed-tree check.
FACT: the alias applies to the Bun main role only. Renderer and preload electron are the injected compat script, owned by F07-T1.
FACT: replacing electron breaks every script that launches the Electron binary or electron-builder. The migrate edit rewrites or removes those scripts in the same edit.
FACT (keld-guard at origin/main 29a4cd7): the live manifest parser ignores the top-level windows key, and keld_permissions_explain refuses channel with KELD-MCP014. Seeded channel grants grant nothing until the KEL-102 amendment from F04-A1's resolution lands. Under that amendment, entries are exact-literal el:<channel>, a miss is KELD-GUARD003, and migrate refuses wildcards. The grant list comes from main-side literal ipcMain registrations; a non-literal registration is reported as unenumerable. X02 owns the migrate side and F04-T3 owns the evaluator.
FACT: fs scopes containing $ are rejected as "unexpanded $VAR scopes are not serviceable", so migrate never emits them. Under legacy, F01-A4 (closed) keeps userData at Electron's default path with raw node:fs and containment forfeited, so the first proof seeds no fs grants. Strict seeding is parked under KEL-78.
FACT (F09-A6, closed): keld.build.ts is not generated for the first proof. The report prints "not generated: keld build is reserved (KELD-CLI-045)". No keld.compat.ts schema or reader exists, so it is not generated either.
FACT (PANEL-D14, closed): electron-updater is aliased to the F09-T1 adapter, whose setFeedURL is a recorded no-op, and DRAWIO_DISABLE_UPDATE=true goes into a declared role environment.
FACT (KEL-75 spec at origin/main 29a4cd7): no live schema carries a declared role environment, and KELD_APP_LINK is the sole child bootstrap variable. The declared role environment has one owner, F01-T4, as an explicit KEL-75 spawn-contract amendment under a permission-model gate. The amendment rejects names beginning KELD_, and the field carries no authority. X02 only writes the declaration and never defines the field.
FACT (KEL-78 spec): the explicit profile: "legacy" key does not exist today. X03-T5 decides its grammar and its single location (it recommends keld.permissions.jsonc). X03-T7 parses the key and stamps authority_profile on records. X02 writes the key into whichever file X03-T5 selects and never decides the location.
FACT (verb and flag sources): migrate is reserved (KELD-CLI-045). keld dev rejects every argument (KELD-CLI-044), so --headless --smoke is not live. The live keld.config.ts reader parses only name, entry and renderer from the hello template shape, which differs from the arch 04 §2 defineConfig sketch.
INFERENCE: install cannot be observed as a prebuilt install until KEL-141 ships a distribution artefact. X02-T5 records the install cell as unknown rather than relabelling a dev-staged run as an install.
UNKNOWN (PANEL-P1): whether draw.io's modified-document close path can run unmodified. If arm B fails, the close cell is scored against a declared one-edit patch ("config + 1 edit"). X02-T6 consumes this through F06-T7 (showMessageBoxSync), which closes either as pass or as a recorded fail cell.
FACT (map as read 2026-10-07): no ticket implements the worker-owned single-link blocking CALL transport that PANEL-P1 selects, and F06-T7 consumes it. The transport is a kipc atom, not an X02 atom. Once the orchestrator mints it (X05 or F04) and adds it to F06-T7, X02-T6 reaches it through F06-T7.
Platform lanes
macOS (Apple Silicon) under the explicit legacy profile is the only first-proof lane. INFERENCE: analysis and generation are platform-neutral, but no Windows or Linux corpus cell is scheduled. Each is an explicit documented gap, and strict is not admitted on any OS.
Executing application code or build/packaging configs (forge configs, afterPack hooks, webpack configs) during analysis
Writing any file without --write, or writing an edit the report does not list with its reversal
Printing a compatibility percentage, a 'score' or an 'expected to run' verdict in migrate output
Seeding wildcard grants ($HOME/**, https://**, file:///**, el:*), host-less globs, $VAR fs scopes the guard rejects, or absolute per-machine paths to make keld dev pass
Deriving channel grants from a preload's page-chosen channel names
Translating autoUpdater.setFeedURL(x) or electron-updater runtime feed values into the privileged updater's feed
Carrying nodeIntegration:true, contextIsolation:false or webSecurity:false forward as allowed configuration
Translating app.commandLine.appendSwitch, disableBlinkFeatures or V8 flags into engine flags (reported as dropped)
Mapping child_process spawn/exec with shell:true or a variable program to a shell.spawn grant
Claiming native-addon support without a KEL-215-shaped version/runtime/digest row
A second electron resolver (bunfig alias, tsconfig paths.electron, Bun preload plugin) beside the package-manifest alias
A second manifest parser or emitter, a second JSONC stripper, a second corpus manifest format or a second compat matrix copy inside migrate
Scoring analyzer counts as a corpus cell, or recording a cell pass on import success
Running Electron's spec/ tree under Bun as the migration oracle
electron-quick-start corpus cells (not in the first-proof denominator)
shell.openExternal grants for draw.io's two literal Help-menu origins and its dynamic openExternal wrapper (not on the four-step path; F06-T3 / X04-D4)
Strict-profile userData/logs seeding (F01-A4 parked under KEL-78)
Web-storage continuity when migrate replaces file:// or custom-scheme origins (F07-A6 parked)
keld.build.ts translation of electron-builder/forge configs (F09-T2, after the keld.build.ts schema spec)
Windows and Linux corpus lanes; strict-profile draw.io
A 20-app corpus and the Tier-2 exit criterion
Specifier resolution, the self-contained CJS-requirable @keld/electron entry and fail-closed role spawn without auto-install (X03-T1)
The channel-grant evaluator (F04-T3) and the KEL-102 amendment text (F04-A1 resolution owner)
The explicit legacy profile key: its location, grammar, parser and ProfileState→authority_profile mapping (X03-T5 spec, X03-T7 implementation, under KEL-78); X02 only writes the key
The declared-role-environment field and its delivery to the role (F01-T4, as a KEL-75 spawn-contract amendment); X02 only writes the declaration
Not yet specified (fog)
Recorder / dev-permissive profile as the source of dynamic grants (arch 03 §3: none in v0)
keld doctor --web-compat scope (rejected today as KELD-CLI-044); no per-OS web-feature baseline exists
keld.compat.ts schema and reader (none exists anywhere)
The install-cell observable before a KEL-141 prebuilt artefact exists (X02-T5 records it unknown)
Owner of the documented committed product-corpus id list (none today)
Host-side $VAR resolution owner for fs scopes
tsc and webpack resolution through the package-manifest alias (untested by anyone)
Bun auto-install behaviour with the alias declared but node_modules absent; any use of bunfig [install] auto (a separate decision per X02-A1)
Runtime-permit contract for dialog-returned paths (F06-D1 parked)
Committed form and size of the compat matrix as the analyzer classification source (X02-T7)
Decisions that govern this unit (closed decision tickets)
Scope rewritten around the first-proof slices (X02-T1, T3, T4, T5, T6) versus next (T2, T7, T8, T9) (critic yagni; X06-D2 pull-order correction)
Corpus demand replaced with resolved call sites and labelled facts: 24 live literal ipcMain channels (program finding said 25, which counts the commented-out log), post-ready lock call, DRAWIO_DISABLE_UPDATE read at top level (refuter extra finding on inflated counts; refuter X02-A5 verdict; PANEL-D15)
Forge-config receipt corrected: load-time hazard is the git-hash helper; pandoc spawn runs in generateAssets (refuter X02-A2 correction a)
Module-alias fact replaced with the closed X02-A1 resolution: one package-manifest resolver, no plugin, no bunfig, tsconfig paths removed; package self-containment and CJS entry routed to X03-T1 (X02-A1 resolution; refuter X02-A1 verdicts; X03 findings)
Alias scope stated as the Bun main role only (refuter extra finding on Zettlr preload)
Seeding facts corrected: channel grants are inert until the KEL-102 amendment, $VAR scopes are rejected, there is no fs seeding under legacy, and the 'live vocabulary' overstatement is removed (refuter X02-A4 corrections; F01-A4 and F04-A1 resolutions)
'Boot facts host-published; blocking CALLs wait on PANEL-P1' rewritten as F01/X03/PANEL-P1 atoms outside X02 (refuter X02-A5 refuted)
keld.build.ts and keld.compat.ts marked not generated with printed reasons (F09-A6 resolution)
Linear owners listed with live status fetched 2026-10-07; KEL-237 corrected from owner to reused pattern (non-goals); added a missing-owner blocker with a decision packet (program-wide finding; X06-D3/D6 corrections)
Maturity ladder sourced to X01-EPIC; analyzer counts never become cells (refuter X02-A6)
Install labelled INFERENCE/UNKNOWN pending KEL-141 (critic ambiguity laundering on install)
Platform lanes: macOS legacy only; Windows/Linux and strict are explicit gaps
Epic now accounts for X02's entities: no Electron API matrix rows, and every migration surface is covered by a ticket or listed under never/out_of_scope/not_yet_specified (repair rule 9)
Declared role environment fact relabelled: KEL-75 makes KELD_APP_LINK the sole bootstrap variable and no live schema carries the field; its single owner is F01-T4 as a KEL-75 amendment (cross-check finding 5: declared role environment owner)
Added the profile-key ownership fact (X03-T5 location and grammar, X03-T7 parser); removed the key from not_yet_specified and added it to out_of_scope (cross-check finding 6: profile key location pre-decided without an X03-T5 edge)
Recorded that the PANEL-P1 blocking-CALL transport has no implementation ticket on the map and will reach X02-T6 through F06-T7 (cross-check finding 3: blocking-CALL transport has no implementation ticket)
Scope now names X02-T6 as the only ticket that flips cells; X02-T4/X02-T5 now consume X01-T3/X01-T4 instead of X01-T1 (cross-check finding 4: X02-T6 gate set incomplete; cross-check finding 2: first-proof slices gated on next-milestone X01-T1)
Audit findings not applied (with the evidence-backed reason)
Critic edge X02-T3: add edges X02-T3 ← F04-A1 and X02-T3 ← F09-A6 — Both are CLOSED decisions, and repair rule 4 forbids closed blockers. Applied in substance instead: F09-A6's resolution drops keld.build.ts from the artefact, and F04-A1's resolution is consumed in X02-T1/X02-T3 as the external task artifact 'KEL-102 per-window channel-grant amendment (not landed)'.
Critic hidden coupling F02-T3/F06-T2/PANEL-P1/X02-T4: create a new 'blocking host CALL from a Bun role' transport atom and split F02-T3 AC1 into unmodified/modified — Both are outside X02. The transport is a kipc atom, and the cross-check confirmed that no unit minted it (see the finding-3 entry). F02-T3 belongs to the F02 repair. X02 applies its own edges (X02-T6 ← PANEL-P1 and F06-T7) and the declared-patch scoring path (X02-T5/X02-T6).
Critic hidden coupling F04-A1/F04-T3/X02-T3: move the 'el:* is refused by migrate' AC from F04-T3 to X02 — The X02 side is applied: X02-T3 has the literal-only check and X02-T8 owns the refusal. Deleting the AC from F04-T3 is a write to another unit. The F04 repair owner must remove it, or the atom keeps two owners.
Refuter extra finding (semantics lens): write bunfig [install] auto = "disable" from migrate to stop Bun auto-installing the real Electron — The closed X02-A1 resolution says any further bunfig use is a separate decision. X02-T3 applies the installed-tree check, and the fail-closed spawn without auto-install is routed to X03-T1 (the role spawn owner), per the X03 refuter's suggested control.
Refuter X02-A5 correction: worker-owned second kipc link as a candidate for blocking CALLs — Refused on the map (PANEL-D4, closed: a second link mints a second principal). It is also not an X02 atom: boot facts are F01-T4/X03-T1 and blocking CALLs are PANEL-P1. X02 records only the corrected draw.io fact (the lock call is post-ready).
Cross-check finding 1, fix option (a): correct adopted_decisions.json X06-D7 to option C — Wrong per primary evidence. GitHub Linear owner for repo-writing Electron-compat slices (owner decision: align to nearest Linear issue, else GitHub is the tracker of record) #517 is closed, and its owner comment (0monish, 2026-10-06T20:32Z, IC_kwDOSwkPJ88AAAABZxzzGA) says 'Option D is adopted for unaligned work by the owner's decision', which supersedes the body's option-C recommendation. The adopted X06-D7 text matches that comment. X02 applies option (b): every X02 ticket now names its GitHub tracker of record and its Linear reference, and the specs are ready-for-agent.
Cross-check finding 2: replace X01-T1 with X01-T3 in F04-T1 and reword F04-T1 AC3 — Applied for X02-T4 and X02-T5: both are now on X01-T3, and X02-T4 is also on X01-T4. F04-T1 is an F04 ticket, so the F04 repair must make that change.
Cross-check finding 3: mint the worker-owned single-link blocking CALL transport ticket (X05-T3 or F04-T18) and add it to F06-T7, F02-T11, F06-T14 and X02-T6 — Not mintable in X02. Rule 1 numbers new tickets within the unit, and the transport is a kipc atom (wire-protocol and public-API gates; owner candidates KEL-80, Backlog and unassigned, or KEL-97). Putting it under the migrate epic would give it the wrong owner, and X05-T3 is already taken by the parked perf run. FACT (repair_result.json, read 2026-10-07): no ticket in any of the 14 repaired units implements the transport. Orchestrator action: mint it in X05 or F04, blocked by PANEL-P1, and add it to F06-T7's blocked_by. X02-T6 already depends on F06-T7, so it reaches the transport transitively. A direct X02-T6 edge cannot reference a key that does not exist yet.
Cross-check finding 4: rename the 'X02-T4 consumes ...' notes in F01/F02/F03/F05/F06/F07/F09/X01 to X02-T6 — Those notes live in other units, so their repairs must make the rename. X02's own text already names X02-T6 as the flipping ticket (epic scope, X02-T4 out_of_scope and notes).
Cross-check finding 5: F01-T4 adds the declared role environment as an explicit KEL-75 schema amendment with a permission-model gate and a KELD_* rejection AC; delete the contrary sentence from F09's unapplied reason — Applied on the X02 side: X02-T1, X02-T3 and the epic now cite F01-T4 under a KEL-75 spawn-contract amendment, and X02-T3 checks that no KELD_ name appears. The F01-T4 field, its gate and its AC are F01 writes, and the F09 sentence is an F09 write; both belong to those repairs. Evidence: the KEL-75 spec at origin/main 29a4cd7 says 'KELD_APP_LINK remains the sole child bootstrap variable' and that a capability exception 'cannot arise from ... an environment value'.
changed the title [-]program(migrate): read-only analyzer, module alias, five-file generation, honest report without percentages, corpus harness manifest[/-][+]program(migrate): read-only analyzer, one package-manifest alias, a hand-authored draw.io first-proof artefact, a report without percentages, and the electron-apps-v0 product corpus[/+]on Oct 6, 2026
Parent map: #391 · Unit: X02
docs/agents/workflow.md§ Tracker issue (rule lands with docs(agents): record the #517 tracker-of-record rule in root AGENTS.md and the workflow claim protocol #520). Linear reference: KEL-127 (Todo) carries a link to this issue.Scope
This epic covers
keld migrate: read-only analysis by default and reversible writes only under--write. It also covers the one module alias an app needs (a package-manifest dependency keyedelectron), the output contract for the Keld config files, the report wording, and the product corpus (electron-apps-v0) that scores real apps through the KEL-74 evidence schema. The first proof needs four slices from this epic: the output-contract spec (X02-T1), a hand-authored draw.io artefact that meets it (X02-T3), the corpus contract spec and manifest with red-until-implemented cells (X02-T5, X02-T4), and the scoring run on macOS (X02-T6), which is the only ticket that flips the corpus cells. The analyzer (X02-T7 spec, X02-T2 first slice, X02-T9 remaining blocker classes) and the--writegenerator (X02-T8) arenext. The first proof does not need them: draw.io's channels and webPreferences can be enumerated by hand from one main file.X02 owns no rows of the 2,128-member Electron v44.4.5 API matrix. Every API member is assigned to F01–F09. The entities X02 owns are the migration surfaces. Each one is either covered by a ticket below or listed under never / out_of_scope / not_yet_specified.
Corpus demand (resolved call sites, not token-scan leads)
ipcMain.on/once. A 25th registration,log, is commented out. The preload forwards channel names chosen by the page, so the preload does not constrain the channel set. UNKNOWN: which of the 24 the web app actually sends, because the webapp submodule is empty in the clone. PANEL-P3 produces that list.requestSingleInstanceLock()runs inside theapp.whenReady().thencallback, which is after ready. The published research said "pre-ready, same pattern as Zettlr", which is wrong for draw.io. Zettlr calls it before ready.DRAWIO_DISABLE_UPDATEis read fromprocess.envat module top level.autoUpdater.setFeedURL({provider:'github',…})is called outside the disable guard. electron-updater, electron-store, electron-log and electron-context-menu all import the bareelectronname.shell.openExternalhas two literal https origins (Help menu items) and one dynamic wrapper.app.getPathis called withuserDataanddocuments.disableBlinkFeaturesis set on every window. Thestartscript iselectron ., five scripts run electron-builder, and the app has no tsconfig.showMessageBoxSync, on the close path. Counts from the receiver-blind token scan (for exampleWebContents.replace 22, or the<webview>hits that are allwebviewTag: false) are leads, not demand.generateAssetshook spawns the pandoc download while packaging. This is why app configs are never executed.Maturity ladder (owned by X01-EPIC)
BEHAVIOR_MATCH → CONFORMANCE_PASS → CORPUS_VERIFIED. Ticket targets: L0 = approved spec; L1 = implemented with tests on macOS; L3 = CORPUS_VERIFIED cells in
electron-apps-v0(panelproduct), withauthority_profile: legacy_sandbox_offprinted. Analyzer counts never become a cell:OperationKindis the closed set install / activation / primary_workflow / full_feature.Linear owners consumed (Linear, fetched 2026-10-07; read-only)
migrateverb's tracking issue points here. Its acceptance criterion "keld migrateUX specified" closed without a spec file. The only UX text is the architecture 04 §1 sample, which X02-T1 corrects.DOCUMENTED_COMMITTED_PRODUCT_CORPORAis empty, so no product percentage can be printed.electron-apps-v0manifest.profile: "legacy"key "does not exist today", and none of its tasks T1–T7 names that key as a deliverable. On the map, X03-T5 owns the key's single location and grammar (a spec amendment under KEL-78) and X03-T7 owns its parser.KELD_APP_LINKremains the sole child bootstrap variable, and a role-specific capability exception cannot arise from an environment value. KEL-102 guard enforcement: In Progress, unassigned. KEL-141 prebuilt distribution: Backlog, unassigned. KEL-103 signed macOS host: In Progress (Amisha Ramani).Tracker of record (owner decision #517, adopted as X06-D7)
## Agent claimblock is posted as a GitHub comment (earliest comment wins, the assignee mirrors it), status and evidence stay on GitHub, and no Linear issue is created. The nearest live Linear issue for the surface (fallback KEL-127) carries a link to the GitHub ticket. This comment supersedes the option-C recommendation in Linear owner for repo-writing Electron-compat slices (owner decision: align to nearest Linear issue, else GitHub is the tracker of record) #517's own body..agents/instructions.mdprotocol, Linear owner for repo-writing Electron-compat slices (owner decision: align to nearest Linear issue, else GitHub is the tracker of record) #517 and map Wayfinder map: KELD Electron Compatibility Program (Electron 44.x baseline) #391 are the documented exception that every claimant must cite. That amendment is a separate owner-authorized change and does not gate X02 tickets.ready-for-agent. The feature and task tickets stayneeds-specbecause their specs have not landed, not because an owner is missing.Design facts (labelled)
electronpointing at @keld/electron. It usesnpm:once the package is published andfile:/link:before that, with package exports mapping all five specifiers to one entry. There is no Bun plugin. The bunfig[alias]is inert on Bun 1.4.2, so migrate never writes it. tsconfigpaths.electrongives Bun-only, silently wrong resolution and can create two module instances, so migrate never writes it and removes it if present. The arch 04 §2/§3 erratum lands in the X02-T1 spec PR.., as ESM TypeScript, and it imports @keld/api by a relative path outside the package. With no node_modules present, Bun auto-installs the realelectronpackage and returns a string with no error. Owner of the self-contained, CJS-requirable entry, the subpath exports and the fail-closed role spawn: X03-T1 (adjacent atom, not X02). X02 owns only the manifest edit and the installed-tree check.electronare the injected compat script, owned by F07-T1.electronbreaks every script that launches the Electron binary or electron-builder. The migrate edit rewrites or removes those scripts in the same edit.windowskey, andkeld_permissions_explainrefuseschannelwith KELD-MCP014. Seeded channel grants grant nothing until the KEL-102 amendment from F04-A1's resolution lands. Under that amendment, entries are exact-literalel:<channel>, a miss is KELD-GUARD003, and migrate refuses wildcards. The grant list comes from main-side literal ipcMain registrations; a non-literal registration is reported as unenumerable. X02 owns the migrate side and F04-T3 owns the evaluator.$are rejected as "unexpanded$VARscopes are not serviceable", so migrate never emits them. Under legacy, F01-A4 (closed) keepsuserDataat Electron's default path with raw node:fs and containment forfeited, so the first proof seeds no fs grants. Strict seeding is parked under KEL-78.setFeedURLis a recorded no-op, andDRAWIO_DISABLE_UPDATE=truegoes into a declared role environment.KELD_APP_LINKis the sole child bootstrap variable. The declared role environment has one owner, F01-T4, as an explicit KEL-75 spawn-contract amendment under a permission-model gate. The amendment rejects names beginningKELD_, and the field carries no authority. X02 only writes the declaration and never defines the field.profile: "legacy"key does not exist today. X03-T5 decides its grammar and its single location (it recommends keld.permissions.jsonc). X03-T7 parses the key and stampsauthority_profileon records. X02 writes the key into whichever file X03-T5 selects and never decides the location.migrateis reserved (KELD-CLI-045).keld devrejects every argument (KELD-CLI-044), so--headless --smokeis not live. The live keld.config.ts reader parses onlyname,entryandrendererfrom the hello template shape, which differs from the arch 04 §2defineConfigsketch.unknownrather than relabelling a dev-staged run as an install.Platform lanes
macOS (Apple Silicon) under the explicit legacy profile is the only first-proof lane. INFERENCE: analysis and generation are platform-neutral, but no Windows or Linux corpus cell is scheduled. Each is an explicit documented gap, and strict is not admitted on any OS.
Tracer-bullet tickets (sub-issues)
X02-T1X02-T2X02-T3X02-T4X02-T5X02-T6X02-T7keld migrate --writegenerator — reproduces the X02-T3 artefact byte-for-byte and passes the X02-T6 activation cell with its own output #591X02-T8X02-T9Never list (documented ✘)
--write, or writing an edit the report does not list with its reversal$HOME/**,https://**,file:///**,el:*), host-less globs,$VARfs scopes the guard rejects, or absolute per-machine paths to makekeld devpassautoUpdater.setFeedURL(x)or electron-updater runtime feed values into the privileged updater's feednodeIntegration:true,contextIsolation:falseorwebSecurity:falseforward as allowed configurationapp.commandLine.appendSwitch,disableBlinkFeaturesor V8 flags into engine flags (reported as dropped)shell:trueor a variable program to ashell.spawngrantelectronresolver (bunfig alias, tsconfigpaths.electron, Bun preload plugin) beside the package-manifest aliasOut of scope
Not yet specified (fog)
keld doctor --web-compatscope (rejected today as KELD-CLI-044); no per-OS web-feature baseline exists$VARresolution owner for fs scopes[install] auto(a separate decision per X02-A1)Decisions that govern this unit (closed decision tickets)
electrondependency alias (X02) vs a Bun preload plugin for the five Electron specifiers (X03) #412X02-A1— 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 theChange log (doctrine-audit repair, 2026-10-07)
log), post-ready lock call, DRAWIO_DISABLE_UPDATE read at top level (refuter extra finding on inflated counts; refuter X02-A5 verdict; PANEL-D15)$VARscopes are rejected, there is no fs seeding under legacy, and the 'live vocabulary' overstatement is removed (refuter X02-A4 corrections; F01-A4 and F04-A1 resolutions)KELD_APP_LINKthe sole bootstrap variable and no live schema carries the field; its single owner is F01-T4 as a KEL-75 amendment (cross-check finding 5: declared role environment owner)Audit findings not applied (with the evidence-backed reason)
[install] auto = "disable"from migrate to stop Bun auto-installing the real Electron — The closed X02-A1 resolution says any further bunfig use is a separate decision. X02-T3 applies the installed-tree check, and the fail-closed spawn without auto-install is routed to X03-T1 (the role spawn owner), per the X03 refuter's suggested control..agents/instructions.md, not an X02 atom. X02 tickets cite the exception in their claim note. Other units' tickets still say 'option C' or 'X06-D6' (for example X01-T3/X01-T4: 'claim on KEL-237 under Linear owner for repo-writing Electron-compat slices (owner decision: align to nearest Linear issue, else GitHub is the tracker of record) #517 option C'); relabelling them belongs to the F01/F02/F03/F04/F05/F06/F07/F09/X01/X03 repairs.KELD_name appears. The F01-T4 field, its gate and its AC are F01 writes, and the F09 sentence is an F09 write; both belong to those repairs. Evidence: the KEL-75 spec at origin/main 29a4cd7 says 'KELD_APP_LINKremains the sole child bootstrap variable' and that a capability exception 'cannot arise from ... an environment value'.