Repository navigation
[SHELL-0] Add shell contracts and measurement baseline - #129
Merged
Merged
Conversation
SHELL-0 (#128), following APP-ARCH-0 (#127). Dormant foundation only: no production page, main or preload loads src/shell. - src/shell: disposable, contribution, services, profiles, command and panel services over the UI-0 registries, tool registry, contextual panels, menu boundary, DocumentSession controller boundary. - Panel and contextual lifecycles are remountable; one record's failure never stops the others; multiple disposal failures are aggregated. - test/shell: focused contract tests, registered in run-tests.js. - qa/shell-0-baseline: repeatable QA baselines for startup, page switch and memory (evidence, not a golden file; pids anonymized). - spikes/shell-0-module-loading: native ESM vs esbuild spike; recommendation ESBUILD_ENTRY_BUNDLES, not activated. - docs/architecture/SHELL_0_CONTRACTS_AND_MEASUREMENTS.md. No product behavior, dependency or repository-policy change. Signed-off-by: Ryan Bundy <ascendance@skate.fm>
The IIFE/export structural check matched LF only, so a Windows CRLF checkout failed it although every module is wrapped. Normalize line endings before the structural checks and prove the check against LF, CRLF and unwrapped/export-less sources. Signed-off-by: Ryan Bundy <ascendance@skate.fm>
Independent QA of PR #129 (RF1, RF2, N2). RF1 contextual-panels: createHost, releaseHost and resolveContext are now isolated like the records. A throwing createHost leaves that record inactive and reconciliation continues; a throwing releaseHost never stops the remaining cleanup; a throwing resolveContext fails closed (every mounted editor disposed, nothing mounted, no update, contextFailed). reconcile() reports every failure in `errors`; dispose + releaseHost failing together yield one AggregateError (ECONTEXTUAL_CLEANUP_FAILED) holding both. RF2 command-service: `profiles` no longer weakens registry validation. A non-function `enabled` is rejected with the registry's own ECOMMAND_INVALID instead of being treated as always enabled. N2 docs: esbuild bundle determinism is stated for a fixed build root / absWorkingDir; deferred QA notes recorded in §21c. src/shell remains unused by production. Signed-off-by: Ryan Bundy <ascendance@skate.fm>
appliesTo() exceptions are logged and treated as not applicable (fail closed); they are not entered in reconcile().errors. errors records the reconciliation lifecycle and host-callback failures (resolveContext, createHost, mount, releaseHost, update, unmount). Narrow the module header and SHELL-0 doc §9, which overstated that every failure is returned. Add one focused assertion that a later record still reconciles in the same pass as a throwing appliesTo. No runtime behaviour change. Signed-off-by: Ryan Bundy <ascendance@skate.fm>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #128 (SHELL-0). Follows APP-ARCH-0 / #127.
This PR does not start #121 or #122.
This PR does not implement the persistent shell.
Full detail:
docs/architecture/SHELL_0_CONTRACTS_AND_MEASUREMENTS.md.Contract modules (
src/shell/, dormant)disposable,contribution,services,profiles,command-service,panel-service,tool-registry,contextual-panels,menu-boundary,document-session. Command/panel services wrap the existing UI-0 registries rather than replacing them. Contracts are layout-neutral (no assumed quad-view, toolbar side, Inspector or Source placement).Product load boundary: no production file loads
src/shell—main.js,preload.js,renderer/**andsrc/**are source-scanned bytest/shell/boundaries.test.js. No command or panel migrated.Lifecycle model
AggregateErrorholding all of them.appliesTo/mount/update/disposeleaves no stale active state and never stops other records reconciling. Host callbacks are isolated the same way: a throwingcreateHostleaves that record inactive, a throwingreleaseHostnever stops remaining cleanup, a throwingresolveContextfails closed (all mounted editors disposed, nothing mounted,contextFailed: true). A throwingappliesTois logged and treated as not applicable (not entered inerrors);reconcile()reports lifecycle and host-callback failures (resolveContext,createHost,mount,releaseHost,update,unmount) inerrors;dispose+releaseHostboth failing → oneAggregateError(ECONTEXTUAL_CLEANUP_FAILED) holding both.profilesadds a gate (profileAllowed && originalEnabled()) and never weakens registry validation — a non-functionenabledis rejected with the registry's ownECOMMAND_INVALID, exactly as for a profile-neutral record.DocumentSession boundary
A controller over existing authorities (CodeMirror text/undo,
sceneSelection, main'sEditorSession) — not a second document. SHELL-0 does not settle the final dirty-baseline owner; Shell-2 must resolve it without creating a second canonical source or undo model.#121 / #122 boundaries
#121 receives the command/panel/tool contracts; #122 receives the renderer menu boundary (
menu-boundary.js). Neither is started here.Measurements (repeatable SHELL-0 QA baselines)
Startup, page-switch and memory baselines via
VisualQaRunner+ capture-server mode (qa/shell-0-baseline/). Linux/X11, Ryzen 9 5900X, Node v24.21.0, Electron 41.7.1,--no-sandbox, warm cache, small fixtures. Not end-user performance claims;RESULTS.jsonis evidence, not a golden file (PIDs anonymized, no paths). Memory: no retained renderer growth proven; main-process +11 MB RSS drift needs a longer soak before classification (not called a leak); old-page memory persists for several navigations before release.ESM spike →
ESBUILD_ENTRY_BUNDLESNative ESM works over
file://in sandboxed Electron 41 but cannot import the shared CommonJSsrc/by name. On a synthetic 42-module graph (X_ITE excluded), one bundle loaded in 11.6 ms vs 33.5 ms — supports the architecture choice, not a guaranteed product speedup. Bundle output is deterministic for a fixed build root /absWorkingDir(esbuild path comments depend on the working directory). Not activated; noCLAUDE.md/policy change.Validation
Candidate
92347a685f76dc9fac53ffbd35af4b85d7626218(independent-QA fix commit for RF1/RF2 on top of2eec9e24):node --test test/shell/*.test.js: 71/71 passnpm run check: 2625 tests — 2621 pass, 0 fail, 4 skip; 327 files parsedsrc/shellcontract code, its tests and the architecture doc):npm run test:visual: pre-existing runner failure under Node 24 (Cannot find module '…/test/visual')WRL_FORGE_ALLOW_VISUAL=1 node --test --test-concurrency=1 test/visual/*.test.js: 20 tests, 18 pass, 2 failbbox == null, reproduced onmainat957102ac) and its parent group[QA] Repair canonical visual test invocation on Node 24,[QA] Investigate pre-existing Extrusion visual bounds failureUnchanged
No user-facing behavior change. No dependency change. No repository-policy change (
CLAUDE.md,package.json, lockfile untouched). Only non-new file:scripts/run-tests.js(+test/shell).