feat(loader): interpolate the entry disabled field

The Windows platform layer disables tool-bash and inserts the pwsh stack, but the shipped presets each mount a tool-bash row that re-enabled the tool on win32 — the session had both a PowerShell-backed bash tool and tool-pwsh, silently, because no spec pinned the composed preset layer.

The Loader now evaluates a disabled: !!js expression against the loader context at every mount decision; disabled is the only interpolated metadata field, and the raw node stays in the options so write-back keeps the !!js form. The standard/code/cordis presets gate tool-bash with process.platform === 'win32', verify-cordis-config allows expressions in disabled only, and the windows-shell spec pins the preset-level invariant.
This commit is contained in:
Huanqi Cao
2026-08-11 11:33:53 +08:00
parent db1028a84d
commit 6fb226ea24
16 changed files with 261 additions and 43 deletions
+1
View File
@@ -48,6 +48,7 @@ Keep this log exhaustive — every divergence from upstream must be listed.
16. **In-memory Loader entry activation in `loader/src/config/entry.ts`**: an invocation can activate a row shipped with `disabled: true` without mutating its serialized options. The override belongs to the mounted entry object, survives Include config reapplication, respects disabled ancestors, and disappears with the entry. Covered by `packages/boot/cmdline/tests/cmdline.spec.ts` and `apps/web/tests/hmr-live.e2e.ts`.
17. **`@deepseek-ai` rescope**: every vendored manifest `name`, every internal dependency entry among the vendored set, and every module specifier that reaches them use the scoped names in the manifest table's `npm name` column. Directory names, version numbers, and dependency ranges are unchanged, and no upstream runtime identifier is renamed — `Symbol.for('schemastery')` and Schemastery's `vendor:` metadata field keep their upstream values. Re-apply with `pnpm run rescope-vendor --apply` after a sync; the table's two name columns are the mapping, restated for consumers in [docs/rescope.md](../docs/rescope.md).
18. **`cordis/package.json` publishes `src`**: added `src` to the `files` list, joining the other eight vendored packages. Cordis declares `"./src/*": "./src/*"` in its exports, so a tarball without `src` publishes an export map pointing at absent files; the release change judgement also reads `files` to decide whether a diff reaches the payload, and a package whose only published paths are build output has no tracked path to match.
19. **Entry `disabled` interpolation in `loader/src/config/entry.ts`**: a `disabled: !!js` expression evaluates against the loader context at every mount decision; the raw node stays in the options, so write-back keeps the `!!js` form. `disabled` is the only interpolated metadata field. Covered by `packages/boot/app-boot/tests/user-patches.spec.ts` and `apps/cli/tests/windows-shell.spec.ts`.
## Sync procedure
+13 -3
View File
@@ -3,7 +3,7 @@ import { deepEqual, isNullable } from '@deepseek-ai/cosmokit'
import { Loader } from '../index.ts'
import { EntryGroup } from './group.ts'
import { EntryTree } from './tree.ts'
import { evaluate } from './utils.ts'
import { evaluate, isJsExpr } from './utils.ts'
/** Static plugin hook for resolving a container config while preserving nested entry configs. */
export const EntryConfigResolver = Symbol.for('cordis.loader.entry-config-resolver')
@@ -101,15 +101,25 @@ export class Entry {
private _disabled(options: EntryOptions) {
// group is always enabled
if (options.group) return false
if (options.disabled && !this.runtimeEnabled) return true
if (this.disabledOf(options) && !this.runtimeEnabled) return true
let entry = this.parent.ctx.fiber.entry
while (entry) {
if (entry.options.disabled && !entry.runtimeEnabled) return true
if (this.disabledOf(entry.options) && !entry.runtimeEnabled) return true
entry = entry.parent.ctx.fiber.entry
}
return false
}
/**
* Effective disabled state: a `!!js` expression evaluates against the loader
* context. The raw node stays in the options, so write-back keeps the form.
*/
private disabledOf(options: EntryOptions): boolean {
return isJsExpr(options.disabled)
? Boolean(this.evaluate(options.disabled.__jsExpr))
: Boolean(options.disabled)
}
/**
* Enable this in-memory entry without rewriting its configured `disabled`
* value; the override survives config reapplication for this entry object.