refactor(bundle): fold the Windows shell platform layer into the base rows
Entry \disabled\ interpolation makes the launcher's separate platform layer unnecessary: the base bundle's cordis.patch.yml now gates both shell stacks on its own rows — bash-sandbox/tool-bash disable on win32, and their twins pwsh-sandbox/tool-pwsh mount only there with the inverted expression — so exactly one shell stack mounts per host from one shared patch file. windows.cordis.patch.yml and the launcher's windows-shell.ts injection (boot, live recomposition, config dumps) are deleted, with the workspace-constraints entry and the dsh-base exports/files entries following. The windows-shell spec pins the effective per-platform roster through the real bundle layers, and base.spec pins the four symmetric gates. The superseded active notes are updated and cross-linked; the loader note records the fold itself.
This commit is contained in:
@@ -15,7 +15,6 @@ import {
|
||||
type ConfigDumpLayer,
|
||||
} from '@deepseek-ai/dsh-app-boot'
|
||||
import { homePatchPath, prepareProfile, PROFILE_ROOT_FILENAME } from './profile-boot.ts'
|
||||
import { resolveWindowsShellLayer } from './windows-shell.ts'
|
||||
|
||||
const NAME = 'dsh'
|
||||
|
||||
@@ -34,12 +33,6 @@ export function runDumpConfig(profile: string, defaultOnly: boolean, patches: re
|
||||
label: layer.packageName,
|
||||
patches: layer.patches,
|
||||
}))
|
||||
// The win32 shell platform layer rides between bundles and user layers,
|
||||
// exactly where the boot applies it.
|
||||
const windowsShellLayer = resolveWindowsShellLayer(process.platform, loaded.layers, NAME)
|
||||
if (windowsShellLayer !== undefined) {
|
||||
layers.push({ label: windowsShellLayer.label, patches: windowsShellLayer.patches })
|
||||
}
|
||||
if (!defaultOnly) {
|
||||
if (existsSync(loaded.patchPath)) {
|
||||
layers.push({ label: loaded.patchPath, patches: loaded.patches })
|
||||
|
||||
@@ -40,7 +40,6 @@ import { DSH_ENVIRONMENT_KEY, type EnvironmentSnapshot } from '@deepseek-ai/dsh-
|
||||
import { provideCmdline } from '@deepseek-ai/dsh-cmdline'
|
||||
import type { HeadlessIo } from '@deepseek-ai/dsh-headless'
|
||||
import { createProcessShutdown, type ProcessShutdown } from './process-shutdown.ts'
|
||||
import { resolveWindowsShellLayer } from './windows-shell.ts'
|
||||
|
||||
const NAME = 'dsh'
|
||||
|
||||
@@ -114,8 +113,6 @@ interface ComposedProfile {
|
||||
profile: Profile
|
||||
/** Bundle layers concatenated — the part below the user layers on a live reload. */
|
||||
bundlePatches: PatchOptions[]
|
||||
/** The win32 shell platform layer (the base bundle's `windows.cordis.patch.yml`), between bundles and user layers. */
|
||||
windowsShellPatches: PatchOptions[]
|
||||
/** The home-level user layer (`$DSH_HOME/cordis.patch.yml`), applied after the profile's own. */
|
||||
homePatches: PatchOptions[]
|
||||
/** Layers above the user layers on a live reload: `--patch` overlays and the telemetry switch. */
|
||||
@@ -131,7 +128,6 @@ interface ComposedProfile {
|
||||
function allPatches(composed: ComposedProfile): PatchOptions[] {
|
||||
return [
|
||||
...composed.bundlePatches,
|
||||
...composed.windowsShellPatches,
|
||||
...composed.profile.patches,
|
||||
...composed.homePatches,
|
||||
...composed.overlays,
|
||||
@@ -140,10 +136,10 @@ function allPatches(composed: ComposedProfile): PatchOptions[] {
|
||||
|
||||
/**
|
||||
* Load `name` and compose its effective patch stack: bundle layers in
|
||||
* `dsh.profile.bundles` order, the win32 shell platform layer (when the host
|
||||
* is Windows), the profile's user layer, the home-level user layer
|
||||
* (`$DSH_HOME/cordis.patch.yml` — machine-local preferences that apply to
|
||||
* every profile, so it outranks the per-profile layer), `--patch` overlays,
|
||||
* `dsh.profile.bundles` order (the base bundle gates the shell stacks by
|
||||
* platform on its own rows), the profile's user layer, the home-level user
|
||||
* layer (`$DSH_HOME/cordis.patch.yml` — machine-local preferences that apply
|
||||
* to every profile, so it outranks the per-profile layer), `--patch` overlays,
|
||||
* then the telemetry switch.
|
||||
* @param name - the profile name.
|
||||
* @param patchFiles - `--patch` overlay paths, in argv order.
|
||||
@@ -157,9 +153,8 @@ function composeProfile(
|
||||
const homePatches = loadOptionalPatches(NAME, homePatchPath()) ?? []
|
||||
const overlays = patchFiles.flatMap(file => loadOverlayPatches(NAME, resolve(file)))
|
||||
const bundlePatches = profile.layers.flatMap(layer => layer.patches)
|
||||
const windowsShellPatches = resolveWindowsShellLayer(process.platform, profile.layers, NAME)?.patches ?? []
|
||||
const rows = new Map<string, EntryOptions>()
|
||||
for (const row of composeEntries([bundlePatches, windowsShellPatches, profile.patches, homePatches, overlays])) {
|
||||
for (const row of composeEntries([bundlePatches, profile.patches, homePatches, overlays])) {
|
||||
if (typeof row.id === 'string') rows.set(row.id, row)
|
||||
}
|
||||
const composedOverlays = [...overlays]
|
||||
@@ -178,7 +173,7 @@ function composeProfile(
|
||||
}
|
||||
const telemetryPatch = resolveTelemetryPatch(process.env.DSH_TELEMETRY_DISABLED, rows.has(TELEMETRY_ROW_ID))
|
||||
if (telemetryPatch !== undefined) composedOverlays.push(telemetryPatch)
|
||||
return { profile, bundlePatches, windowsShellPatches, homePatches, overlays: composedOverlays, rows }
|
||||
return { profile, bundlePatches, homePatches, overlays: composedOverlays, rows }
|
||||
}
|
||||
|
||||
/** Options for {@link runProfile}. */
|
||||
@@ -241,7 +236,6 @@ export async function runProfile(options: RunProfileOptions): Promise<{ ctx: Con
|
||||
// removing the override could never revert the row to the bundle default.
|
||||
const composeLive = (): PatchOptions[] => structuredClone([
|
||||
...composed.bundlePatches,
|
||||
...composed.windowsShellPatches,
|
||||
...loadOptionalPatches(NAME, composed.profile.patchPath) ?? [],
|
||||
...loadOptionalPatches(NAME, homePatchPath()) ?? [],
|
||||
...composed.overlays,
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* The Windows shell platform layer: on win32 hosts the shipped profile
|
||||
* compositions swap the POSIX-only bash stack for the sandbox-confined
|
||||
* PowerShell stack (`@deepseek-ai/dsh-pwsh-sandbox` +
|
||||
* `@deepseek-ai/dsh-tool-pwsh`). The layer is the base bundle's
|
||||
* `windows.cordis.patch.yml`, injected by the launcher between the bundle
|
||||
* layers and the user layers so a user patch can still override it — the
|
||||
* only override channel is composition config, like every other roster
|
||||
* decision. POSIX hosts never receive the layer.
|
||||
* @module @deepseek-ai/dsh/windows-shell
|
||||
*/
|
||||
|
||||
import { join } from 'node:path'
|
||||
import type { PatchOptions } from '@deepseek-ai/cordis-plugin-include'
|
||||
import { loadOverlayPatches, type ProfileLayer } from '@deepseek-ai/dsh-app-boot'
|
||||
|
||||
/** The base bundle whose package carries the Windows shell patch. */
|
||||
export const BASE_BUNDLE = '@deepseek-ai/dsh-base'
|
||||
|
||||
/** The Windows shell patch filename inside the base bundle package. */
|
||||
export const WINDOWS_SHELL_PATCH_FILENAME = 'windows.cordis.patch.yml'
|
||||
|
||||
/** One Windows shell platform layer: its patch file and parsed patches. */
|
||||
export interface WindowsShellLayer {
|
||||
/** The patch file path, used as the config-dump provenance label. */
|
||||
label: string
|
||||
/** The parsed patch entries, applied after the bundle layers. */
|
||||
patches: PatchOptions[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the Windows shell platform layer for a profile composition.
|
||||
* @param platform - the host platform (`process.platform` at call sites).
|
||||
* @param layers - the profile's bundle layers, in application order.
|
||||
* @param binName - the diagnostic prefix on thrown errors (`dsh`).
|
||||
* @returns the pwsh layer on win32, else `undefined`. A custom profile that
|
||||
* mounts no base bundle is skipped (it owns its shell stack); a base
|
||||
* bundle whose Windows shell patch is missing fails loud in
|
||||
* {@link loadOverlayPatches} — the shipped package always carries it, so
|
||||
* a miss is a broken installation.
|
||||
*/
|
||||
export function resolveWindowsShellLayer(
|
||||
platform: NodeJS.Platform,
|
||||
layers: readonly ProfileLayer[],
|
||||
binName: string,
|
||||
): WindowsShellLayer | undefined {
|
||||
if (platform !== 'win32') return undefined
|
||||
const base = layers.find(layer => layer.packageName === BASE_BUNDLE)
|
||||
if (base === undefined) return undefined
|
||||
const label = join(base.packageDir, WINDOWS_SHELL_PATCH_FILENAME)
|
||||
return { label, patches: loadOverlayPatches(binName, label) }
|
||||
}
|
||||
Reference in New Issue
Block a user