fix(coding): remediate ML-07 plugin authority

This commit is contained in:
2026-08-27 20:40:58 +08:00
parent 9407c67df2
commit cf13aa7eba
29 changed files with 1008 additions and 214 deletions

View File

@@ -34,7 +34,7 @@ async function temporaryRoot(prefix: string): Promise<string> {
return root;
}
async function configuredProject(): Promise<string> {
async function configuredProject(skillIds: readonly string[] = ['agent-browser', 'grilling']): Promise<string> {
const root = await temporaryRoot('makelore-pi-products-');
await createCodingProjectMetadata(root, { now: '2026-08-23T00:00:00.000Z' });
await createCodingProjectAgent(root, {
@@ -44,7 +44,7 @@ async function configuredProject(): Promise<string> {
name: 'Builder',
model: null,
modelResolution: 'required',
skillIds: ['agent-browser', 'grilling'],
skillIds: [...skillIds],
responsibility: {
mission: 'Implement changes', owns: [], boundaries: [], collaborators: [], principles: [],
},
@@ -58,11 +58,19 @@ async function configuredProject(): Promise<string> {
return root;
}
function productTools(root: string): PiProductTools {
function productTools(root: string, withDataService = false): PiProductTools {
return new PiProductTools({
browser: {} as AgentBrowserModule,
attachments: new CodingAttachmentStore(path.join(root, 'attachments')),
bundledSkillsDir: path.resolve('resources/coding-skills'),
...(withDataService ? {
pluginSkillSources: [{
id: 'data-service',
pluginId: 'makelore.data-service',
directory: path.resolve('resources/coding-plugins/data-service'),
entryPath: 'skills/data-service/SKILL.md',
}],
} : {}),
});
}
@@ -138,6 +146,39 @@ describe('PI-105 product Host composition', () => {
expect(serialized).not.toMatch(/"(todo|share|revert|unrevert)"/);
});
it('retains a disabled assigned plugin Skill but only makes it effective after enable', async () => {
const root = await configuredProject(['data-service']);
const tools = productTools(root, true);
let enabled = false;
const host = createCodingProductHost({
projects: projectService(root),
productTools: tools,
getEnabledPluginIds: async () => enabled ? ['makelore.data-service'] : [],
});
await expect(host.listSkills()).resolves.not.toContainEqual(
expect.objectContaining({ id: 'data-service' }),
);
await expect(host.listSkills('builder')).resolves.toContainEqual(
expect.objectContaining({
id: 'data-service', selected: true, available: false, effective: false,
}),
);
await expect(host.listCommands(conversationId)).resolves.not.toContainEqual(
expect.objectContaining({ skillId: 'data-service' }),
);
enabled = true;
await expect(host.listSkills('builder')).resolves.toContainEqual(
expect.objectContaining({
id: 'data-service', selected: true, available: true, effective: true,
}),
);
await expect(host.listCommands(conversationId)).resolves.toContainEqual(
expect.objectContaining({ skillId: 'data-service' }),
);
});
it('reads exact-run changes from the same PiProductTools tracker instance', async () => {
const root = await configuredProject();
await writeFile(path.join(root, 'notes.txt'), 'baseline\n', 'utf8');