fix(review): validate skill roots at mount and isolate provider default roots
ds-review-bot round 1 on the repository-plugin runtime: - a manifest-declared skill root absent or non-directory in the installed package now fails the plugin load (skill-local treats a missing root as legitimately empty, which silently mounted a skill-less plugin) - includeDefaultRoots: false no longer inherits $DSH_BUNDLED_SKILL_DIR, so isolated repository providers see only their explicit roots - prepared wrapper baseUrl schema requires the file: scheme, failing hostile URLs at the declared validation boundary - preparedPath reuses format.ts's isOutside; SERVER_NAME_PATTERN is exported and pinned equal to dsh-mcp-client's, with the restatement justified (the prepare bin keeps a zod-only module graph); the unexplained `as never` cast now carries its schemastery rationale - the import-free wrapper assertion also rejects dynamic import( - the headless fixture wrapper is regenerated by the real prepareDshPlugin and a drift test pins fixture == generator output - prepareDshPlugin JSDoc states the non-atomic publish repair contract
This commit is contained in:
@@ -820,6 +820,22 @@ describe('LocalSkillProvider', () => {
|
||||
await ctx.plugin(SkillLocal, { watch: false })
|
||||
expect((await ctx.skills.list()).map(skill => skill.name)).toEqual(['env-bundled-skill', 'env-skill'])
|
||||
|
||||
// Isolated providers see only their explicit roots: the environment
|
||||
// bundled root is a default root, so includeDefaultRoots: false must
|
||||
// drop it — repository providers never re-claim the app's builtins.
|
||||
const isolated = new Context()
|
||||
await isolated.plugin(SkillService)
|
||||
const customOnly = join(envHome, 'custom-only')
|
||||
await writeSkill(customOnly, 'custom-isolated-skill', 'Custom isolated skill')
|
||||
await isolated.plugin(SkillLocal, {
|
||||
providerName: 'isolated',
|
||||
includeDefaultRoots: false,
|
||||
customSkillDirs: [customOnly],
|
||||
watch: false,
|
||||
})
|
||||
expect((await isolated.skills.list()).map(skill => skill.name)).toEqual(['custom-isolated-skill'])
|
||||
await isolated.fiber.dispose()
|
||||
|
||||
process.env.DSH_HOME = join(envHome, 'empty-dsh')
|
||||
delete process.env.DSH_BUNDLED_SKILL_DIR
|
||||
process.env.DSH_AGENTS_HOME = join(envHome, 'empty-agents')
|
||||
|
||||
Reference in New Issue
Block a user