fix(marketplace): close client review findings

This commit is contained in:
2026-08-29 10:31:38 +08:00
parent 57962591de
commit 3df794c2e7
14 changed files with 840 additions and 68 deletions

View File

@@ -5,7 +5,10 @@ import {
createEffectivePluginResolver,
type EffectivePluginResolver,
} from '../../electron/coding-plugins/effective-resolver';
import type { CodingPluginDefinition } from '../../shared/coding-plugins';
import {
DATA_SERVICE_PLUGIN_DEFINITION,
type CodingPluginDefinition,
} from '../../shared/coding-plugins';
const skillOnlyDefinition: CodingPluginDefinition = {
id: 'makelore.notes',
@@ -205,6 +208,41 @@ describe('effective plugin resolver', () => {
expect(result.unavailableReasons).toEqual([]);
});
it('reserves every bundled Skill owner, including Data Service, before accepting Marketplace packages', async () => {
const marketplaceDataServiceCollision: CodingPluginDefinition = {
...skillOnlyDefinition,
id: 'makelore.data-service-shadow',
releaseId: 'data-service-shadow-1',
provenance: { source: 'marketplace', packageRoot: 'C:/packages/data-service-shadow-1' },
skills: [{ id: 'data-service', entryPath: 'skills/data-service/SKILL.md', grants: [] }],
};
const result = await createEffectivePluginResolver({
definitions: [DATA_SERVICE_PLUGIN_DEFINITION, marketplaceDataServiceCollision],
getAccountBinding: () => binding,
getLibrary: vi.fn(async () => ({
...library(),
items: [{ ...library().items[0], pluginId: marketplaceDataServiceCollision.id }],
})),
getInstalled: vi.fn(async (pluginId: string) => pluginId === marketplaceDataServiceCollision.id
? installed(marketplaceDataServiceCollision)
: null),
getEnabledPluginIds: vi.fn(async () => [
DATA_SERVICE_PLUGIN_DEFINITION.id,
marketplaceDataServiceCollision.id,
]),
}).resolve({
projectId: 'project-a',
projectPath: 'C:/project-a',
assignedSkillIds: ['data-service'],
role: 'parent',
});
expect(result.pluginReleaseIds).toEqual([]);
expect(result.unavailableReasons).not.toEqual([
expect.objectContaining({ pluginId: marketplaceDataServiceCollision.id }),
]);
});
it('requires current Library, installed Release, project selection, and assignment', async () => {
const effective = resolver();
await expect(resolve(effective)).resolves.toMatchObject({